<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Concurrency on A Blog for the Uninitialized</title><link>https://www.nilpointer.blog/tags/concurrency/</link><description>Recent content in Concurrency on A Blog for the Uninitialized</description><generator>Hugo</generator><language>en-us</language><copyright>&lt;a href="https://www.apache.org/licenses/LICENSE-2.0" target="_blank" rel="noopener"&gt;Licensed under Apache 2.0&lt;/a&gt;</copyright><lastBuildDate>Fri, 27 Feb 2026 14:29:51 -0800</lastBuildDate><atom:link href="https://www.nilpointer.blog/tags/concurrency/index.xml" rel="self" type="application/rss+xml"/><item><title>Using the "done" channel in Go</title><link>https://www.nilpointer.blog/posts/2026/02/using-the-done-channel-in-go/</link><pubDate>Fri, 27 Feb 2026 14:29:51 -0800</pubDate><guid>https://www.nilpointer.blog/posts/2026/02/using-the-done-channel-in-go/</guid><description>&lt;p&gt;I wanted to document how a &lt;code&gt;done&lt;/code&gt; channel is most commonly used.&lt;/p&gt;
&lt;p&gt;Mainly because I&amp;rsquo;ve personally found it to be more confusing than it should be.&lt;/p&gt;
&lt;p&gt;It usually looks a bit like this, when following a worker pattern:&lt;/p&gt;
&lt;pre tabindex="0"&gt;&lt;code&gt;func main() {
 var doneCh = make(chan struct{})

 // Perform some concurrent work
 // ...

 // Wait on that work
 for i := 0; i &amp;lt; 10; i++ {
 &amp;lt;-doneCh
 }
 
 // complete
}
&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;I intentially left out a bit here to highlight what a &amp;ldquo;done&amp;rdquo; channel actually looks like.&lt;/p&gt;</description></item><item><title>The Worker Pattern</title><link>https://www.nilpointer.blog/posts/2026/02/the-worker-pattern/</link><pubDate>Thu, 26 Feb 2026 16:09:17 -0800</pubDate><guid>https://www.nilpointer.blog/posts/2026/02/the-worker-pattern/</guid><description>&lt;p&gt;I really like using a worker pattern with &lt;a href="https://www.nilpointer.blog/posts/2026/02/golangs-unbuffered-and-buffered-channels/"
 
 
&gt;unbuffered channels&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;API calls, especially when each can be handled separately and independently, are easily implemented with this pattern, and I&amp;rsquo;ve seen it help tremendously when downloading artifacts for building in CI, for example.&lt;/p&gt;
&lt;p&gt;Instead of setting up a buffered channel with a capacity of 10 in an attempt to concurrently handle 10 requests, you can create an unbuffered channel and read from it using 10 workers.&lt;/p&gt;</description></item><item><title>Golang's unbuffered and buffered channels</title><link>https://www.nilpointer.blog/posts/2026/02/golangs-unbuffered-and-buffered-channels/</link><pubDate>Wed, 25 Feb 2026 16:40:18 -0800</pubDate><guid>https://www.nilpointer.blog/posts/2026/02/golangs-unbuffered-and-buffered-channels/</guid><description>&lt;p&gt;From the &lt;a href="https://go.dev/blog/codelab-share"
 
 
 target="_blank" 
 rel="noopener noreferrer"
 
&gt;official Go Blog&lt;/a&gt;:&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Do not communicate by sharing memory; instead, share memory by communicating.&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;They&amp;rsquo;re awesome because they enable concurrency support &amp;ldquo;out of the box&amp;rdquo;.&lt;/p&gt;
&lt;p&gt;They&amp;rsquo;re basically their own type that implements concurrent safe logic of sharing memory locations of data without the explicit usage of mutexes or locks. The example in the blog link above has some code blocks that show this quite well, actually.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;They can be buffered or unbuffered.&lt;/strong&gt;&lt;/p&gt;</description></item></channel></rss>