<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>API on BurrowedInCode</title><link>https://burrowedincode.dev/tags/api/</link><description>Recent content in API on BurrowedInCode</description><generator>Hugo</generator><language>en-us</language><copyright>BurrowedInCode</copyright><lastBuildDate>Fri, 30 Oct 2026 00:00:00 +0000</lastBuildDate><atom:link href="https://burrowedincode.dev/tags/api/index.xml" rel="self" type="application/rss+xml"/><item><title>File Creation Shenanigans</title><link>https://burrowedincode.dev/posts/file-creation-shenanigans/</link><pubDate>Fri, 30 Oct 2026 00:00:00 +0000</pubDate><guid>https://burrowedincode.dev/posts/file-creation-shenanigans/</guid><description>&lt;h1 id="file-creation-shenanigans"&gt;File Creation Shenanigans&lt;/h1&gt;&#10;&lt;p&gt;Lately I&amp;rsquo;ve been working on building a &lt;a href="https://github.com/BurrowedInCode/godl"&gt;concurrent CLI download manager with Go&lt;/a&gt;. Initially I wrote the following function to download a file:&lt;/p&gt;&#10;&lt;div class="highlight"&gt;&lt;pre tabindex="0" style="color:#e0def4;background-color:#191724;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;"&gt;&lt;code class="language-go" data-lang="go"&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e6a86"&gt;// Excerpt from Download: HTTP and progress-reporting code omitted.&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#31748f"&gt;if&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;_&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt; &lt;span style="color:#908caa"&gt;:=&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;os&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Stat&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;outputPath&lt;/span&gt;&lt;span style="color:#908caa"&gt;);&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt; &lt;span style="color:#908caa"&gt;==&lt;/span&gt; &lt;span style="color:#31748f"&gt;nil&lt;/span&gt; &lt;span style="color:#908caa"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#31748f"&gt;return&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;fmt&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Errorf&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#f6c177"&gt;&amp;#34;output file already exists: %s&amp;#34;&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;outputPath&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#908caa"&gt;}&lt;/span&gt; &lt;span style="color:#31748f"&gt;else&lt;/span&gt; &lt;span style="color:#31748f"&gt;if&lt;/span&gt; &lt;span style="color:#908caa"&gt;!&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;errors&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Is&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;err&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;os&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;ErrNotExist&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt; &lt;span style="color:#908caa"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#31748f"&gt;return&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;fmt&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Errorf&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#f6c177"&gt;&amp;#34;check output file: %w&amp;#34;&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#908caa"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e6a86"&gt;// ... fetch the HTTP response ...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ebbcba"&gt;partPath&lt;/span&gt; &lt;span style="color:#908caa"&gt;:=&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;outputPath&lt;/span&gt; &lt;span style="color:#908caa"&gt;+&lt;/span&gt; &lt;span style="color:#f6c177"&gt;&amp;#34;.part&amp;#34;&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#ebbcba"&gt;partFile&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt; &lt;span style="color:#908caa"&gt;:=&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;os&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Create&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;partPath&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#31748f"&gt;if&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt; &lt;span style="color:#908caa"&gt;!=&lt;/span&gt; &lt;span style="color:#31748f"&gt;nil&lt;/span&gt; &lt;span style="color:#908caa"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#31748f"&gt;return&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;fmt&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Errorf&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#f6c177"&gt;&amp;#34;create file: %w&amp;#34;&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#908caa"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#6e6a86"&gt;// ... stream into partFile, close it, and check both operations for errors ...&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#31748f"&gt;if&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt; &lt;span style="color:#908caa"&gt;:=&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;os&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Rename&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;partPath&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;outputPath&lt;/span&gt;&lt;span style="color:#908caa"&gt;);&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt; &lt;span style="color:#908caa"&gt;!=&lt;/span&gt; &lt;span style="color:#31748f"&gt;nil&lt;/span&gt; &lt;span style="color:#908caa"&gt;{&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#ebbcba"&gt;_&lt;/span&gt; &lt;span style="color:#908caa"&gt;=&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;os&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Remove&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;partPath&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&#9;&lt;span style="color:#31748f"&gt;return&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;fmt&lt;/span&gt;&lt;span style="color:#908caa"&gt;.&lt;/span&gt;&lt;span style="color:#ebbcba"&gt;Errorf&lt;/span&gt;&lt;span style="color:#908caa"&gt;(&lt;/span&gt;&lt;span style="color:#f6c177"&gt;&amp;#34;rename file: %w&amp;#34;&lt;/span&gt;&lt;span style="color:#908caa"&gt;,&lt;/span&gt; &lt;span style="color:#ebbcba"&gt;err&lt;/span&gt;&lt;span style="color:#908caa"&gt;)&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;span style="display:flex;"&gt;&lt;span&gt;&lt;span style="color:#908caa"&gt;}&lt;/span&gt;&#10;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Initially, I check whether the destination file exists. If it does, I return an error. However, this check does not reserve the file name. Another process could create the destination while my download is still running. After receiving the HTTP response headers, I construct a temporary path by appending &lt;code&gt;.part&lt;/code&gt; to the destination filename. I then use &lt;code&gt;os.Create&lt;/code&gt; to open a file for writing, creating it if it does not exist or truncating it if it already exists. The response body is then streamed into the temporary file. After streaming completes successfully, I close the temporary file and check for errors before renaming it to the destination filename.&lt;/p&gt;</description></item></channel></rss>