<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:cc="http://cyber.law.harvard.edu/rss/creativeCommonsRssModule.html">
    <channel>
        <title><![CDATA[justforfunc - Medium]]></title>
        <description><![CDATA[The blog posts related to the justforfunc YouTube series that you can watch on justforfunc.com - Medium]]></description>
        <link>https://medium.com/justforfunc?source=rss----7dad93227ded---4</link>
        <image>
            <url>https://cdn-images-1.medium.com/proxy/1*TGH72Nnw24QL3iV9IOm4VA.png</url>
            <title>justforfunc - Medium</title>
            <link>https://medium.com/justforfunc?source=rss----7dad93227ded---4</link>
        </image>
        <generator>Medium</generator>
        <lastBuildDate>Wed, 04 Nov 2026 18:16:07 GMT</lastBuildDate>
        <atom:link href="https://medium.com/feed/justforfunc" rel="self" type="application/rss+xml"/>
        <webMaster><![CDATA[yourfriends@medium.com]]></webMaster>
        <atom:link href="http://medium.superfeedr.com" rel="hub"/>
        <item>
            <title><![CDATA[Analyzing the performance of Go functions with benchmarks]]></title>
            <link>https://medium.com/justforfunc/analyzing-the-performance-of-go-functions-with-benchmarks-60b8162e61c6?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/60b8162e61c6</guid>
            <category><![CDATA[golang-tutorial]]></category>
            <category><![CDATA[benchmark]]></category>
            <category><![CDATA[justforfunc]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 12 Feb 2018 17:40:18 GMT</pubDate>
            <atom:updated>2018-02-12T23:23:52.127Z</atom:updated>
            <content:encoded><![CDATA[<p>This blog post is complementary to <a href="https://www.youtube.com/watch?v=t9bEg2A4jsw">episode 28 of justforfunc</a> which you can watch right below.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F2AulMm-hsdI%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D2AulMm-hsdI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F2AulMm-hsdI%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1dd9bbc599093beea74e92a590e2a00/href">https://medium.com/media/e1dd9bbc599093beea74e92a590e2a00/href</a></iframe><p>In the <a href="https://medium.com/justforfunc/two-ways-of-merging-n-channels-in-go-43c0b57cd1de">previous blog post</a> I discussed two different ways of merging n channels in Go, but we did not discuss which ones was faster. In the meanwhile a third way of merging channels was proposed in <a href="https://www.youtube.com/watch?v=B64hIRjNvLc&amp;lc=Ugzegqi-_YDVei6e0Kp4AaABAg">a YouTube comment</a>.</p><p>This blog post will show that third way and compare all of them from a performance point of view, analyzed using benchmarks.</p><h3>A third way of merging channels</h3><p>Two episodes ago we discussed how two channels could be merged, using a single goroutine and nil channels. We’ll refer to <a href="https://github.com/campoy/justforfunc/blob/master/26-nil-chans/main.go#L19">that function</a> here as <a href="https://github.com/campoy/justforfunc/blob/master/26-nil-chans/main.go#L19">mergeTwo</a>. A <a href="https://justforfunc.com/">justforfunc</a> viewer proposed a way to use this function and recursion to provide a way to merge n channels.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/812/1*lUC7eOZR-V1U8msU_8M39w.png" /><figcaption>merging N channels using recursion</figcaption></figure><p>The solution is quite smart. If we have:</p><ul><li>one channel, we return that channel.</li><li>two channels or more, we merge a half of the channels and then merge them using the result of those using the efficient function.</li></ul><p>What about no channels? We will return an already closed channel.</p><p>Written in code it would look like this:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/da247f5960233a635ef63f3d1a66ecf4/href">https://medium.com/media/da247f5960233a635ef63f3d1a66ecf4/href</a></iframe><p>This is a nice solution that avoids using reflection and also reduces the number of goroutines needed. On the other hand, it uses more channels than before!</p><p>So, which one is fastest? Time for benchmarks!</p><h3>Writing a benchmark</h3><p>Testing and benchmarks are integrated very tightly with the Go tooling, and writing a benchmark is as simple as writing a function with a name starting with Benchmark and the appropriate signature.</p><p>The only parameter a benchmark receives is of type testing.B and it defines the number of times we should perform the operation we’re benchmarking. This is done for statistical significance, by default benchmarks are given a number of iterations that will make the function run for a whole second.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/582d8d554fc6c022bf36a9b166526426/href">https://medium.com/media/582d8d554fc6c022bf36a9b166526426/href</a></iframe><p>Ok, so now we know pretty much everything we need to know to write a benchmark for one of our functions.</p><h3>Benchmarking all our functions</h3><p>Ok, so we’re ready to write benchmarks for each function!</p><p>One for merge:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/472d8ff929fe4a5553cca361b7edf889/href">https://medium.com/media/472d8ff929fe4a5553cca361b7edf889/href</a></iframe><p>One for mergeReflect:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dfb9360939379f11662f4b77ed9c75a5/href">https://medium.com/media/dfb9360939379f11662f4b77ed9c75a5/href</a></iframe><p>And finally. one for mergeRec:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d76c0dea8e02e0ca2a468de6b254505f/href">https://medium.com/media/d76c0dea8e02e0ca2a468de6b254505f/href</a></iframe><p>And now we can finally run them!</p><pre>➜ go test -bench=.<br>goos: darwin<br>goarch: amd64<br>pkg: github.com/campoy/justforfunc/27-merging-chans<br>BenchmarkMerge-4                  200000              7074 ns/op<br>BenchmarkMergeReflect-4           100000             11904 ns/op<br>BenchmarkMergeRec-4               500000              2475 ns/op<br>PASS<br>ok      github.com/campoy/justforfunc/27-merging-chans  4.077s</pre><p>Great, so using recursion is the fastest possible option. Let’s believe it for now!</p><h3>Using sub-benchmarks and b.Run</h3><p>Unfortunately, in order to benchmark three functions we’re repeating lots of code. Wouldn’t it be nice if we could write our benchmark once?</p><p>We can write a function that iterates over our three functions:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b8edaba7fd72de85cb8d7c15615549d3/href">https://medium.com/media/b8edaba7fd72de85cb8d7c15615549d3/href</a></iframe><p>Unfortunately, that simply gives a single and pretty meaningless measure, mixing all performances.</p><pre>➜ go test -bench=.<br>goos: darwin<br>goarch: amd64<br>pkg: github.com/campoy/justforfunc/27-merging-chans<br>BenchmarkMerge-4           50000             22440 ns/op<br>PASS<br>ok      github.com/campoy/justforfunc/27-merging-chans  1.386s</pre><p>Luckily, we can easily create subbenchmarks by calling testing.B.Run, similarly as subtests with testing.T.Run. In order to do so, we need a name, which is actually a pretty good idea from a documentation point of view, anyway.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/b4202336cec9b9d3e2f4906f4575e9c0/href">https://medium.com/media/b4202336cec9b9d3e2f4906f4575e9c0/href</a></iframe><p>When we run these benchmarks we’ll now see three different results as we wished.</p><pre>➜ go test -bench=.<br>goos: darwin<br>goarch: amd64<br>pkg: github.com/campoy/justforfunc/27-merging-chans<br>BenchmarkMerge/goroutines-4               200000          6145 ns/op<br>BenchmarkMerge/reflect-4                  200000         10962 ns/op<br>BenchmarkMerge/recursion-4                500000          2368 ns/op<br>PASS<br>ok      github.com/campoy/justforfunc/27-merging-chans  4.829s</pre><p>Sweet! With way less code we’re still able to benchmark all of our functions.</p><h4>Benchmarking multiple values of N</h4><p>So far we’ve seen that for a single channel the recursive algorithm is the fastest, but what about other values of N?</p><p>We could probably just change the value of N many times and see how it goes. But we could also just use a for loop!</p><p>In the code below we iterate over the powers of 2 from 1 to 1024, and use a combination of the function we’re benchmarking and the value of N as the benchmark name.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/2270630d73375f0e85dba8392f9a44f3/href">https://medium.com/media/2270630d73375f0e85dba8392f9a44f3/href</a></iframe><p>Let’s run the benchmarks!</p><pre>➜ go test -bench=.<br>goos: darwin<br>goarch: amd64<br>pkg: github.com/campoy/justforfunc/27-merging-chans<br>BenchmarkMerge/goroutines/1-4             200000          6919 ns/op<br>BenchmarkMerge/goroutines/2-4             100000         13212 ns/op<br>BenchmarkMerge/goroutines/4-4              50000         25469 ns/op<br>BenchmarkMerge/goroutines/8-4              30000         50819 ns/op<br>BenchmarkMerge/goroutines/16-4             20000         88566 ns/op<br>BenchmarkMerge/goroutines/32-4             10000        162391 ns/op<br>BenchmarkMerge/goroutines/64-4              5000        299955 ns/op<br>BenchmarkMerge/goroutines/128-4             3000        574043 ns/op<br>BenchmarkMerge/goroutines/256-4             1000       1129372 ns/op<br>BenchmarkMerge/goroutines/512-4             1000       2251411 ns/op<br>BenchmarkMerge/goroutines/1024-4             300       4760560 ns/op<br>BenchmarkMerge/reflect/1-4                200000         10868 ns/op<br>BenchmarkMerge/reflect/2-4                100000         22335 ns/op<br>BenchmarkMerge/reflect/4-4                 30000         54882 ns/op<br>BenchmarkMerge/reflect/8-4                 10000        148218 ns/op<br>BenchmarkMerge/reflect/16-4                 3000        543921 ns/op<br>BenchmarkMerge/reflect/32-4                 1000       1694021 ns/op<br>BenchmarkMerge/reflect/64-4                  200       6102920 ns/op<br>BenchmarkMerge/reflect/128-4                 100      22648976 ns/op<br>BenchmarkMerge/reflect/256-4                  20      90204929 ns/op<br>BenchmarkMerge/reflect/512-4                   3     383579039 ns/op<br>BenchmarkMerge/reflect/1024-4                  1    1676544681 ns/op<br>BenchmarkMerge/recursion/1-4              500000          2658 ns/op<br>BenchmarkMerge/recursion/2-4              100000         14707 ns/op<br>BenchmarkMerge/recursion/4-4               30000         44520 ns/op<br>BenchmarkMerge/recursion/8-4               10000        114676 ns/op<br>BenchmarkMerge/recursion/16-4               5000        261880 ns/op<br>BenchmarkMerge/recursion/32-4               3000        560284 ns/op<br>BenchmarkMerge/recursion/64-4               2000       1117642 ns/op<br>BenchmarkMerge/recursion/128-4              1000       2242910 ns/op<br>BenchmarkMerge/recursion/256-4               300       4784719 ns/op<br>BenchmarkMerge/recursion/512-4               100      10044186 ns/op<br>BenchmarkMerge/recursion/1024-4              100      20599475 ns/op<br>PASS<br>ok      github.com/campoy/justforfunc/27-merging-chans  61.533s</pre><p>We can see that even though the recursive algorithm is the fastest for a single channel, very quick the solution with many goroutines outperforms the others.</p><p>We can also this by plotting these numbers with some quick Python. Stop acting shocking I somtimes write in Python too!</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a86948eb9044fd70dac56f3ddc4bf386/href">https://medium.com/media/a86948eb9044fd70dac56f3ddc4bf386/href</a></iframe><figure><img alt="" src="https://cdn-images-1.medium.com/max/382/0*fIMkZRkqlkp09Tm5.png" /></figure><p>It’s hard to see the difference, so let’s use a logarithmic scale for the Y axis (simply add plt.yscale(&#39;log&#39;)).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/378/0*nKZQ1pwXMQ1UeheD.png" /></figure><h3>Managing the benchmark timer</h3><p>There’s an obvious issue with the way we’re measuring performance. We’re also counting the time it takes to create the N channels for our tests, which adds cost that is not relevant to our algorithms.</p><p>We can avoid this by using b.StopTimer() and b.StartTimer().</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8abd411187d36fad19c4945220c55139/href">https://medium.com/media/8abd411187d36fad19c4945220c55139/href</a></iframe><p>The results are not that different to our previous benchmark, but we can see the timing difference increases with the value of N.</p><h3>Can we make them faster?</h3><p>We finally have a good view of how each function performs for different sizes of N. This is great, but doesn’t really help us making our functions faster.</p><p>How could we know more? Well, benchmarks take us only so far, but the next tool we we can use is profiling! Wanna know more? Next episode coming up in two weeks.</p><h3>Thanks</h3><p>If you enjoyed this episode make sure you share it and subscribe to <a href="http://justforfunc.com/">justforfunc</a>! Also, consider sponsoring the series on <a href="https://patreon.com/justforfunc">patreon</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=60b8162e61c6" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/analyzing-the-performance-of-go-functions-with-benchmarks-60b8162e61c6">Analyzing the performance of Go functions with benchmarks</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Two ways of merging N channels in Go]]></title>
            <link>https://medium.com/justforfunc/two-ways-of-merging-n-channels-in-go-43c0b57cd1de?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/43c0b57cd1de</guid>
            <category><![CDATA[justforfunc]]></category>
            <category><![CDATA[coding]]></category>
            <category><![CDATA[channel]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[concurrency]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 29 Jan 2018 16:54:54 GMT</pubDate>
            <atom:updated>2018-02-12T17:49:41.890Z</atom:updated>
            <content:encoded><![CDATA[<h4>Using goroutines and reflection</h4><p>This blog post is complementary to <a href="https://www.youtube.com/watch?v=B64hIRjNvLc">episode 27 of justforfunc</a> which you can watch right below.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FB64hIRjNvLc%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DB64hIRjNvLc&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FB64hIRjNvLc%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/1bd59975e343f25b5a94c96300db66c7/href">https://medium.com/media/1bd59975e343f25b5a94c96300db66c7/href</a></iframe><p>Two weeks ago I explained how nil channels were useful for some important concurrency patterns, specifically when <a href="https://medium.com/justforfunc/why-are-there-nil-channels-in-go-9877cc0b2308">merging two channels</a>. As a result, because this is the internet, many replied telling me there’s better ways to merge two channels than that. And guess what, I agree!</p><p>The algorithm I showed is useful for only two channels. Today we’re going to explore how to handle nchannels where n is not known at compilation time. This means we can’t simply use select over all the channels, so what are the options?</p><h4>First way: using N goroutines</h4><p>The first approach is to create a new goroutine per channel. Each one of these goroutines will range over a channel and send each one of those elements to the output channel.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*oNO9-NZHuTerKDym.png" /><figcaption>schema: we create a new goroutine (circle) per channel (channel looking thingy)</figcaption></figure><p>Or in code:</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/84915b143624036cae37199e3e0ca996/href">https://medium.com/media/84915b143624036cae37199e3e0ca996/href</a></iframe><p>This code is wrong in a couple of ways. Can you see them?</p><p>Let’s first see one of the issues. In order to run it I define a new asChan function, which is explained in the <a href="https://medium.com/justforfunc/why-are-there-nil-channels-in-go-9877cc0b2308">previous justforfunc episode</a>, and use it from the main function as follows.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/a7207390587187ea1720e7e6d5b98a96/href">https://medium.com/media/a7207390587187ea1720e7e6d5b98a96/href</a></iframe><p>Ok, so what’s the problem when we run it when the data race detector enabled, aka -race?</p><pre>$ go run -race main.go<br>==================<br>WARNING: DATA RACE<br>Read at 0x00c420090018 by goroutine 9:<br>  main.merge.func1()<br>      /Users/francesc/src/github.com/campoy/campoy.cat/site/content/blog/main.go:35 +0x3f</pre><pre>Previous write at 0x00c420090018 by main goroutine:<br>  main.merge()<br>      /Users/francesc/src/github.com/campoy/campoy.cat/site/content/blog/main.go:33 +0xf0<br>  main.main()<br>      /Users/francesc/src/github.com/campoy/campoy.cat/site/content/blog/main.go:13 +0x282</pre><pre>Goroutine 9 (running) created at:<br>  main.merge()<br>      /Users/francesc/src/github.com/campoy/campoy.cat/site/content/blog/main.go:34 +0x9b<br>  main.main()<br>      /Users/francesc/src/github.com/campoy/campoy.cat/site/content/blog/main.go:13 +0x282<br>==================</pre><h4>Fixing a data race</h4><p>Indeed, we’re accessing the c variable defined in the for loop from many goroutines. This is dangerous, but luckily there’s a common idiom that solves the problem. Simply pass the variable as a parameter, that way it will be duplicated and each goroutine will end up with a different variable to itself.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7fe6643d84276987ee6dfac846638743/href">https://medium.com/media/7fe6643d84276987ee6dfac846638743/href</a></iframe><p>Now that the data race has been removed, let’s run the program again.</p><pre>$ go run main.go<br>20<br>10<br>0<br>...<br>9<br>fatal error: all goroutines are asleep - deadlock!</pre><pre>goroutine 1 [chan receive]:<br>main.main()<br>        /Users/francesc/src/github.com/campoy/campoy.cat/site/content/blog/main.go:13 +0x24a<br>exit status 2</pre><p>Ok, this is better and it looks pretty good until the end when everything crashes. What’s going on? Well, the main goroutine is blocked waiting for anyone to close the channel on which it’s ranging. Unfortunately we forgot to close the channel at all.</p><h4>Closing the output channel</h4><p>When should we close the channel? Well, once all goroutines have finished sending values into it. When exactly is that? We don’t really know, but we can simply “wait” for them to be done.</p><p>And how do you wait for a group of things? A WaitGroup, defined in the sync package.</p><p>A WaitGroup has 3 main methods: - Add adds a given number of things to be done. - Done indicates one of those things is done. - Wait blocks until the number of things to be done goes down to zero.</p><p>Let’s fix our program and close the output channel when it’s appropriate.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e46946fc7775b7151c9019ba5ac35c48/href">https://medium.com/media/e46946fc7775b7151c9019ba5ac35c48/href</a></iframe><p>Note that Wait is called in a different goroutine.</p><h4>Second way: using reflect.Select</h4><p>A second way of solving the same problem is using reflect.Select which provides a Select operation on a slice of SelectCases.</p><p>In order to call it we’re going to create a slice of SelectCase that contains an element per channel.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/0f72cce62e5dd2b480a7a4f59f66f09a/href">https://medium.com/media/0f72cce62e5dd2b480a7a4f59f66f09a/href</a></iframe><p>Then we can call reflect.Select and send the value we receive to the out channel. Unless channel we received from was closed, in which case we should remove the case from the slice. This is very similar to what we did setting the channel to nil in the previous episode.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/07f987a215cf79f4ffab4f323184767b/href">https://medium.com/media/07f987a215cf79f4ffab4f323184767b/href</a></iframe><p>This should be done for as long there’s at least a non closed channel. In our case this is equivalent to the slice not being empty.</p><p>So the full code is as follows.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1958b67b616700700ceb66c7d1174d48/href">https://medium.com/media/1958b67b616700700ceb66c7d1174d48/href</a></iframe><p>Running this code will also work and finish without panicking.</p><h4>Which one is fastest?</h4><p>The first solution uses a linear number of goroutines (one per channel) so that could somehow get slow at some point.</p><p>But the second solution uses reflection and we all know that’s pretty slow, right?</p><p>So which one is fastest? I sincerely don’t know! And that’s the question I’ll solve in the next episode when we’ll talk about benchmarks.</p><p>You can now read it <a href="https://medium.com/justforfunc/analyzing-the-performance-of-go-functions-with-benchmarks-60b8162e61c6">here</a>!</p><p><a href="https://medium.com/justforfunc/analyzing-the-performance-of-go-functions-with-benchmarks-60b8162e61c6">Analyzing the performance of Go functions with benchmarks</a></p><h3>Thanks</h3><p>If you enjoyed this episode make sure you share it and subscribe to <a href="http://justforfunc.com/">justforfunc</a>! Also, consider sponsoring the series on <a href="https://patreon.com/justforfunc">patreon</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=43c0b57cd1de" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/two-ways-of-merging-n-channels-in-go-43c0b57cd1de">Two ways of merging N channels in Go</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[JustForFunc: “hello, world” and a code review]]></title>
            <link>https://medium.com/justforfunc/justforfunc-hello-world-and-a-code-review-b84998e2f935?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/b84998e2f935</guid>
            <category><![CDATA[google-cloud-platform]]></category>
            <category><![CDATA[videos]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:08:50 GMT</pubDate>
            <atom:updated>2016-07-22T20:48:40.505Z</atom:updated>
            <content:encoded><![CDATA[<p>For the last couple of months I’ve been enjoying how <a href="https://twitter.com/mpjme">MPJ</a> rocks the programming world with his series <a href="https://www.youtube.com/channel/UCO1cgjhGzsSYb1rsB4bFe4Q">funfunfunction</a>. He inspired me to create my own channel so I will be hacking and talking about good code.</p><p>I’m a Developer Advocate for Google Cloud Platform and work with the Go team, so I’ll mostly be writing in Go and running things on Google Cloud … but not only!</p><p>The first episode is obviously number zero:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F0NTKMKDsCTE%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D0NTKMKDsCTE&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F0NTKMKDsCTE%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/c743837944f2c5a2976318e210b26a4a/href">https://medium.com/media/c743837944f2c5a2976318e210b26a4a/href</a></iframe><p>And the second one is already available, where I review some code recently written by a friend on GitHub:</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FeIWFnNz8mF4%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DeIWFnNz8mF4&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FeIWFnNz8mF4%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/a032a2ff8e7141a670a220739467afd6/href">https://medium.com/media/a032a2ff8e7141a670a220739467afd6/href</a></iframe><p>If you enjoyed these videos you should definitely register to the YouTube channel for more! I’ll try to post stuff weekly, at least at the beginning.</p><p>You can send proposals for topics and projects by commenting on the videos, or on Twitter as <a href="https://twitter.com/francesc">@francesc</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fvideoseries%3Flist%3DPL64wiCrrxh4Jisi7OcCJIUpguV_f5jGnZ&amp;url=https%3A%2F%2Fwww.youtube.com%2Fplaylist%3Flist%3DPL64wiCrrxh4Jisi7OcCJIUpguV_f5jGnZ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F0NTKMKDsCTE%2Fhqdefault.jpg%3Fcustom%3Dtrue%26w%3D320%26h%3D180%26stc%3Dtrue%26jpg444%3Dtrue%26jpgq%3D90%26sp%3D68%26sigh%3D7ZURT8s9hSU_BKu43UXiTtGliz0&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="853" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/377b6b0143f92653d5f954c6c6b38de2/href">https://medium.com/media/377b6b0143f92653d5f954c6c6b38de2/href</a></iframe><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=b84998e2f935" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/justforfunc-hello-world-and-a-code-review-b84998e2f935">JustForFunc: “hello, world” and a code review</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The Magic Gate #justforfunc 3]]></title>
            <link>https://medium.com/justforfunc/the-magic-gate-justforfunc-3-abcd629ec6ce?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/abcd629ec6ce</guid>
            <category><![CDATA[google-cloud-platform]]></category>
            <category><![CDATA[twilio]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[speech-recognition]]></category>
            <category><![CDATA[app-engine]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:08:40 GMT</pubDate>
            <atom:updated>2016-08-30T22:34:01.700Z</atom:updated>
            <content:encoded><![CDATA[<p>A month ago I was having dinner with my team and we ended up talking about cool demos we could build with Google Cloud Speech API. Someone mentioned it would be a good way of answering phone calls … wait … phone calls!? ☎️</p><p>For almost a year I’ve been living in this apartment where whenever rings at the gate downstairs my phone will ring, then I have to press the button 9 to open the door. I’m sure you’ve seen some of these systems before … they work, but I also find it pretty annoying to have to answer the phone every time. So …</p><blockquote>could I use speech recognition to open the gate with a spoken password?</blockquote><p>That’s a demo! And actually, if you think about it it’s not too far from the door/paintings in Harry Potter!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2F3-bXjK_5C8g%3Ffeature%3Doembed&amp;display_name=YouTube&amp;url=https%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3D3-bXjK_5C8g&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2F3-bXjK_5C8g%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/165dfb2c00983e2f8303c442a1a2f481/href">https://medium.com/media/165dfb2c00983e2f8303c442a1a2f481/href</a></iframe><p>Anyway, I decided it was a great opportunity to build a demo using Twilio and Google Cloud Speech API together. I had never used any of those before, so the video ended up being longer that expected… but here they are!</p><p>Part 1: I build the basic architecture using Google App Engine and Twilio to open the door regardless of who is calling.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FmTd3hHUy9OU%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DmTd3hHUy9OU&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FmTd3hHUy9OU%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/947fa4853e20521431314267d8e76ee9/href">https://medium.com/media/947fa4853e20521431314267d8e76ee9/href</a></iframe><p>Part 2: I add speech recognition by recording the phone call and sending the mp3 to Google Cloud Speech API.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FuIA1s3Rhpv8%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DuIA1s3Rhpv8&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FuIA1s3Rhpv8%2Fhqdefault.jpg&amp;key=d04bfffea46d4aeda930ec88cc64b87c&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/ede4a1e66b6cf9028826ffaed0574331/href">https://medium.com/media/ede4a1e66b6cf9028826ffaed0574331/href</a></iframe><p>I hope you enjoy them 😊</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=abcd629ec6ce" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/the-magic-gate-justforfunc-3-abcd629ec6ce">The Magic Gate #justforfunc 3</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Using the Go execution tracer to speed up fractal rendering]]></title>
            <link>https://medium.com/justforfunc/using-the-go-execution-tracer-to-speed-up-fractal-rendering-c06bb3760507?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/c06bb3760507</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[performance]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:08:31 GMT</pubDate>
            <atom:updated>2017-11-01T01:21:32.822Z</atom:updated>
            <content:encoded><![CDATA[<blockquote>Originally posted on <a href="https://campoy.cat/blog/using-the-go-tracer-to-speed-up-fractal-making/">campoy.cat</a></blockquote><p>As an experiment, this is the first blog post form of a <a href="https://www.youtube.com/watch?v=ySy3sR1LFCQ">justforfunc</a> episode, you can also watch the corresponding episode.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FySy3sR1LFCQ%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DySy3sR1LFCQ&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FySy3sR1LFCQ%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/0c90ceda46e9314311e1f02766860656/href">https://medium.com/media/0c90ceda46e9314311e1f02766860656/href</a></iframe><h3>The initial program</h3><p>We start with a very simple program, copied partly from <a href="https://en.wikipedia.org/wiki/Mandelbrot_set">Wikipedia</a>, that creates a Mandelbrot fractal by first computing the color of each pixel, and then writing the corresponding image to a PNG file.</p><pre>func main() {<br>	f, err := os.Create(output)<br>	if err != nil {<br>		log.Fatal(err)<br>	}</pre><pre>	img := createSeq(width, height)</pre><pre>	if err = png.Encode(f, img); err != nil {<br>		log.Fatal(err)<br>	}<br>}</pre><p>In this first iteration createSeq, which calls pixel to compute the color of each pixel, one after the other.</p><pre>func createSeq(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))<br>	for i := 0; i &lt; width; i++ {<br>		for j := 0; j &lt; height; j++ {<br>			m.Set(i, j, pixel(i, j, width, height))<br>		}<br>	}<br>	return m<br>}</pre><p>Finally, the part that is basically extracted from Wikipedia allows us to compute the color of a given pixel. The complexity value determines how complex the fractal gets, values from 4 to 2048 give various and interesting effects. Play with this!</p><pre>func pixel(i, j, width, height int) color.Color {<br>	// Play with this constant to increase the complexity of the fractal.<br>	// In the justforfunc.com video this was set to 4.<br>	const complexity = 1024</pre><pre>	xi := norm(i, width, -1.0, 2)<br>	yi := norm(j, height, -1, 1)</pre><pre>	const maxI = 1000<br>	x, y := 0., 0.</pre><pre>	for i := 0; (x*x+y*y &lt; complexity) &amp;&amp; i &lt; maxI; i++ {<br>		x, y = x*x-y*y+xi, 2*x*y+yi<br>	}</pre><pre>	return color.Gray{uint8(x)}<br>}</pre><h3>How fast is it?</h3><p>At this point our program runs and creates a cool fractal, and it takes (in my laptop) around 4.7 seconds.</p><pre>$ time ./mandelbrot<br>./mandelbrot  4.44s user 0.01s system 99% cpu 4.466 total</pre><p>The resulting image is this cool fractal.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*VX3UQ3d0SHLZmF-d.png" /></figure><h3>Can we make it faster? pprof</h3><p>In order to obtain more information about how the program performs we can profile the CPU usage with the runtime/pprof package in the standard library.</p><p>Simply adding two lines of code at the beginning of the main function.</p><pre>pprof.StartCPUProfile(os.Stdout)<br>defer pprof.StopCPUProfile()</pre><p>Now if we run the program again it will output pprof profiling information into the standard output.</p><pre>$ time ./mandelbrot &gt; cpu.pprof<br>./mandelbrot &gt; cpu.pprof  5.25s user 0.02s system 96% cpu 5.469 total</pre><p>Interestingly, adding pprof has not slowed the program much! And in exchange of that temporary performance hit we get much visibility on what the program spent its time on.</p><p>Let’s open pprof and see what it spent its time on.</p><pre>$ go tool pprof cpu.pprof<br>Type: cpu<br>Time: Oct 23, 2017 at 11:04am (CEST)<br>Duration: 5.45s, Total samples = 4.53s (83.13%)<br>Entering interactive mode (type &quot;help&quot; <strong>for</strong> commands, &quot;o&quot; <strong>for</strong> options)<br>(pprof)</pre><p>We can now list how much time we spend in each function we call with list.</p><pre>(pprof) list main.main<br>Total: 4.53s<br>ROUTINE ======================== main.main <strong>in</strong> /Users/campoy/src/github.com/campoy/justforfunc/22-perf/main.go<br>         0      4.15s (flat, cum) 91.61% of Total<br>         .          .     39:   f, err := os.Create(output)<br>         .          .     40:   <strong>if</strong> err != nil {<br>         .          .     41:           log.Fatal(err)<br>         .          .     42:   }<br>         .          .     43:<br>         .      3.89s     44:   img := createSeq(width, height)<br>         .          .     45:<br>         .      260ms     46:   <strong>if</strong> err = png.Encode(f, img); err != nil {<br>         .          .     47:           log.Fatal(err)<br>         .          .     48:   }<br>         .          .     49:}<br>         .          .     50:<br>         .          .     51:// createSeq fills one pixel at a time.</pre><p>Ok, so it seems we spent most of the time in createSeq, makes sense!</p><pre>(pprof) list main.createSeq<br>Total: 4.53s<br>ROUTINE ======================== main.createSeq <strong>in</strong> /Users/campoy/src/github.com/campoy/justforfunc/22-perf/main.go<br>         0      3.89s (flat, cum) 85.87% of Total<br>         .          .     51:// createSeq fills one pixel at a time.<br>         .          .     52:func createSeq(width, height int) image.Image {<br>         .          .     53:   m := image.NewGray(image.Rect(0, 0, width, height))<br>         .          .     54:   <strong>for</strong> i := 0; i &lt; width; i++ {<br>         .          .     55:           <strong>for</strong> j := 0; j &lt; height; j++ {<br>         .      3.89s     56:                   m.Set(i, j, pixel(i, j, width, height))<br>         .          .     57:           }<br>         .          .     58:   }<br>         .          .     59:   return m<br>         .          .     60:}<br>         .          .     61:</pre><p>Great, again most of the time is in the line calling pixel, and what does pixel do?</p><pre>(pprof) list main.pixel<br>Total: 4.53s<br>ROUTINE ======================== main.pixel <strong>in</strong> /Users/campoy/src/github.com/campoy/justforfunc/22-perf/main.go<br>     2.01s      3.87s (flat, cum) 85.43% of Total<br>         .          .    209:func pixel(i, j, width, height int) color.Color {<br>         .          .    210:   // Play with this constant to increase the complexity of the fractal.<br>         .          .    211:   // In the justforfunc.com video this was set to 4.<br>         .          .    212:   const complexity = 1024<br>         .          .    213:<br>         .       10ms    214:   xi := norm(i, width, -1.0, 2)<br>         .          .    215:   yi := norm(j, height, -1, 1)<br>         .          .    216:<br>         .          .    217:   const maxI = 1000<br>         .          .    218:   x, y := 0., 0.<br>         .          .    219:<br>     1.29s      1.29s    220:   <strong>for</strong> i := 0; (x*x+y*y &lt; complexity) &amp;&amp; i &lt; maxI; i++ {<br>     720ms      720ms    221:           x, y = x*x-y*y+xi, 2*x*y+yi<br>         .          .    222:   }<br>         .          .    223:<br>         .      1.85s    224:   return color.Gray{uint8(x)}<br>         .          .    225:}</pre><p>Ok, so we spend a decent amount of time computing multiplications in that loop, also a lot of time allocating pixels in line 224.</p><h3>So what now?</h3><p>We have a better idea of what our program spends most of the time: computing pixel values. But what do we do now? It seems reasonable that a program that generates fractals spends most of the time, well … generating fractals!</p><p>There’s things we could do to try and optimize the CPU time, but in this post instead of going that way, we’re going to see what other things we can do to speed up the program without changing the pixelfunction.</p><h3>Meet the tracer</h3><p>One of the problems of pprof is that it is a stastistical way of discovering how often a given piece of code is running. It allows us to understand what the program is running when it’s on the CPU, but what about when it’s not? We’re missing information that we can not (or at least not easily) extract from a pprof trace.</p><p>The Go execution tracer, rather than pinging the program regularily to understand what it is up to, it instead hooks to the Go runtime to log every single event we care about. These events include:</p><ul><li>go routine creation and destruction</li><li>blocking events such as channel or mutex operations</li><li>system calls</li><li>etc</li></ul><p>The most powerful side of the Go execution tracer is the amazing visualization it generates, which allows us to see the “empty” space in our program.</p><p>Let’s create a trace from this program, by simply replacing our pprof calls by calls to the runtime/tracepackage also in the standard library.</p><pre>trace.Start(os.Stdout)<br>defer trace.Stop()</pre><p>Then we can execute the program again an visualize the trace with go tool trace.</p><pre>$ time ./mandelbrot &gt; seq.trace<br>./mandelbrot &gt; seq.trace  5.11s user 0.04s system 99% cpu 5.176 total</pre><pre>$ go tool seq.trace<br>2017/10/23 11:16:55 Parsing trace...<br>2017/10/23 11:16:55 Serializing trace...<br>2017/10/23 11:16:55 Splitting trace...<br>2017/10/23 11:16:55 Opening browser</pre><p>This will open a browser and display a webpage that, among others, has a link to View Trace. Click there and you should be something like this:</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*A4Hd3JfVitXdS_pR.png" /></figure><p>I invite you to explore the visualization, specially the garbage collection event towards the end. But the most important point here is everything we can’t see.</p><p>Do you see those 8 Proc? Those are the eight processors that my laptop has. Only one of them, processor 2 in my case, is really doing any work!</p><p>One of Go’s powers is easy concurrency, right? Well, it’s time to use those, because we clearly are wasting CPU time by not expressing our program in a concurrent way which would enable parallelism.</p><h3>More concurrency, more parallelism, more speed!</h3><p>Let’s go to a ridiculuous extreme and decide that, since each pixel can be computed concurrently, we are going to create a goroutine per pixel. This, for our 2048x2048 image, means we’re going to create over four million goroutines. We say goroutines are cheap … so let’s seee if that’s true!</p><p>The function that creates a goroutine per pixel is called createPixel:</p><pre>func createPixel(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))<br>	var w sync.WaitGroup<br>	w.Add(width * height)<br>	for i := 0; i &lt; width; i++ {<br>		for j := 0; j &lt; height; j++ {<br>			go func(i, j int) {<br>				m.Set(i, j, pixel(i, j, width, height))<br>				w.Done()<br>			}(i, j)<br>		}<br>	}<br>	w.Wait()<br>	return m<br>}</pre><p>Ok, so first of all let’s run it without the tracer to see how fast it is and compare it to the sequential option.</p><pre>$ time ./mandelbrot<br>./mandelbrot  13.70s user 1.53s system 471% cpu 3.234 total</pre><p>Wow, it’s actually faster! It used much more CPU time (13.70s) but since it distributed it so efficiently across our eight CPUs, the total time it spent running was only 3.2 seconds.</p><p>Victory! Right?</p><p>Well, let’s create a trace and see what it looks like.</p><pre>$ time ./mandelbrot &gt; px.trace<br>./mandelbrot &gt; px.trace  25.64s user 5.46s system 502% cpu 6.184 total</pre><p>Wow, we spent almost twice of CPU cycles than before! Why is this? Well, the tracer has a performance cost, and in this case we’re logging each and every goroutine we create. This, by itself, might point to problem in our solution.</p><p>Let’s open the trace, and be warned it’s not going to be fast!</p><pre>$ go tool trace px.trace<br>2017/10/23 11:29:17 Parsing trace...<br>2017/10/23 11:29:58 Serializing trace...<br>2017/10/23 11:30:13 Splitting trace...<br>2017/10/23 11:30:49 Opening browser</pre><blockquote><em>Note: you will need to pass the binary as before px.trace if you are using Go 1.8 or earlier versions.</em></blockquote><p>The trace has been split into many pieces to avoid overloading the browser. Let’s open one somewhere around the center. This, again, will be quite slow. Patience is your friend.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*_yioZxiDKJgYY5FR.png" /></figure><p>It seems like the CPUs are <em>really</em> busy this time! But, let’s zoom in a bit.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*DOJkrU9sgT-Uvid9.png" /></figure><p>Oh, that doesn’t seem like it’s very well utilized after all. We’ve created too many goroutines, which causes too much pressure on the runtime, both the scheduler and the garbage collector, and it shows as contention and wasted CPU time.</p><h3>On go routines and dataraces</h3><p>Ok, so … is this program correct? Are there any data races? The easiest way to show that there are no obvious data races is by using the data race detector.</p><p>To do so you can simply add -race to the go build|run|test command. If you try it with the program as is it will fail:</p><pre>$ go build -o mandelbrot -race<br>$ time ./mandelbrot<br>race: limit on 8192 simultaneously alive goroutines is exceeded, dying<br>./mandelbrot  0.49s user 1.00s system 99% cpu 1.483 total</pre><p>There’s a limit of 8192 alive goroutines, and with 4 millions we clearly exceed it. Instead let’s use the benchmarks I wrote, which generate smaller images.</p><p>Let’s run it with and without the data race detector to compare the performances.</p><pre>$ go test -bench=Pixel<br>goos: darwin<br>goarch: amd64<br>pkg: github.com/campoy/justforfunc/22-perf<br>BenchmarkPixel/64-8                 2000           1003116 ns/op<br>BenchmarkPixel/128-8                 300           5003258 ns/op<br>BenchmarkPixel/256-8                 100          19693236 ns/op<br>BenchmarkPixel/512-8                  20          86670280 ns/op<br>PASS<br>ok      github.com/campoy/justforfunc/22-perf   7.894s</pre><pre>$ go test -bench=Pixel -race<br>go test -bench=Pixel -race<br>goos: darwin<br>goarch: amd64<br>pkg: github.com/campoy/justforfunc/22-perf<br>BenchmarkPixel/64-8                   10         181391401 ns/op<br>BenchmarkPixel/128-8                   2         729349776 ns/op<br>BenchmarkPixel/256-8                   1        2923114988 ns/op<br>BenchmarkPixel/512-8                   1        12477182754 ns/op<br>PASS<br>ok      github.com/campoy/justforfunc/22-perf   20.626s</pre><p>There’s a clear difference, but the good news it’s it didn’t panic. This means no data races were detected. There might be some data race, but the code we just run didn’t cause any.</p><p>In a previous version of the code (see the video for more details) the anonymous function in the go routine didn’t get any parameters. This caused a data race on both i and j.</p><pre>func createPixel(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))<br>	var w sync.WaitGroup<br>	w.Add(width * height)<br>	for i := 0; i &lt; width; i++ {<br>		for j := 0; j &lt; height; j++ {<br>			go func() {<br>				m.Set(i, j, pixel(i, j, width, height))<br>				w.Done()<br>			}()<br>		}<br>	}<br>	w.Wait()<br>	return m<br>}</pre><p>It’s also worth mentioning that m.Set being called from different go routines is not a problem since we are modifying different positions in a preallocated slice.</p><h3>Finding compromise in between too few and too many</h3><p>Ok, so one goroutine is too few, but four millions is too many. Let’s go right in between and go with one goroutine per column. This time we’ll call createCol which creates a goroutine per column, so “only” 2048 of them.</p><pre>func createCol(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))<br>	var w sync.WaitGroup<br>	w.Add(width)<br>	for i := 0; i &lt; width; i++ {<br>		go func(i int) {<br>			for j := 0; j &lt; height; j++ {<br>				m.Set(i, j, pixel(i, j, width, height))<br>			}<br>			w.Done()<br>		}(i)<br>	}<br>	w.Wait()<br>	return m<br>}</pre><p>As before, let’s run it without trace first to see whether we improve the 3.2 seconds we got before.</p><pre>$ time ./mandelbrot<br>./mandelbrot  4.90s user 0.02s system 499% cpu 0.985 total</pre><p>Ok, we went from almost five seconds, to three, and now less than a second!</p><p>What does the trace look like? Let’s check it out.</p><pre>$ time ./mandelbrot &gt; col.trace<br>./mandelbrot &gt; col.trace  4.79s user 0.02s system 498% cpu 0.966 total</pre><pre>$ go tool trace col.trace<br>2017/10/23 11:41:29 Parsing trace...<br>2017/10/23 11:41:29 Serializing trace...<br>2017/10/23 11:41:30 Splitting trace...<br>2017/10/23 11:41:30 Opening browser</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ZWZFtmvvNl2OENHx.png" /></figure><p>That looks pretty good! We can see that the CPUs are pretty busy first, then we move to one goroutine to encode the image into the file. Let’s zoom in, though (feeling like CSI already?).</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*J11l5VOUfhAawoJ_.png" /></figure><p>That looks very good! But, can we do better?</p><h3>What about the “workers” concurrency pattern?</h3><p>If you’ve written enough Go, you migh have encountered the “workers” pattern, where we create a small number of workers (eight in this case) which fetch tasks from a channel. We also use a sync.WaitGroup to make sure all workers are done before exiting.</p><pre>func createWorkers(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))</pre><pre>	type px struct{ x, y int }<br>	c := make(chan px)</pre><pre>	var w sync.WaitGroup<br>	for n := 0; n &lt; numWorkers; n++ {<br>		w.Add(1)<br>		go func() {<br>			for px := range c {<br>				m.Set(px.x, px.y, pixel(px.x, px.y, width, height))<br>			}<br>			w.Done()<br>		}()<br>	}</pre><pre>	for i := 0; i &lt; width; i++ {<br>		for j := 0; j &lt; height; j++ {<br>			c &lt;- px{i, j}<br>		}<br>	}<br>	close(c)<br>	w.Wait()<br>	return m<br>}</pre><p>We have a smaller number of goroutines, but definitely enough of them to distribute across all processors. This should be faster, right?</p><p>Well, never trust your instincts when it comes to performance analysis.</p><p>Let’s run it and see, first without the tracer.</p><pre>$ time ./mandelbrot<br>./mandelbrot  10.31s user 3.22s system 422% cpu 3.201 total</pre><p>Ok, so this is not better than creating a pixel per goroutine! Why? Well, time to trace.</p><pre>$ time ./mandelbrot &gt; workers.trace<br>./mandelbrot &gt; workers.trace  30.86s user 13.88s system 383% cpu 11.660 total</pre><pre>$ go tool trace workers.trace<br>2017/10/23 11:49:20 Parsing trace...<br>2017/10/23 11:49:52 Serializing trace...<br>2017/10/23 11:50:02 Splitting trace...<br>2017/10/23 11:50:49 Opening browser</pre><p>This is again incredibly slow, so clearly we’re logging many events. What are those events?</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*PZuuEf68GbRYQ-MU.png" /></figure><p>Again it seems quite good from far away, but when you zoom in it looks quite different.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*ci5BO-ku7V8ZsI0U.png" /></figure><p>Where is the contention coming from now? The runtime should be totally fine with eight goroutines, 2048 was not too many. Well, let’s go back to the menu where we clicked “View Trace” but instead let’s click Synchronization blocking profile. You’ll see a graph generated by our old friend pprof. In this graph we can see the contention due to synchronization primitives such as channels and mutexes.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*Zau_-AfclT89FDot.png" /></figure><p>So our goroutines spent almost 48 seconds blocked receiving from a channel! That’s, obviously, a problem.</p><p>Why is this? Our channel is being used as a way to communicate between the main goroutine sending pixels, and the workers. This happens 4 million times, which causes a lot of contention. How could be avoid most of this contention?</p><h3>Buffered channels!</h3><p>Buffered channels in this case will make most of the send and receive operations non blocking! You don’t trust me? You don’t need to. Let’s modify the program to use a channel with a buffer of a size that allows us to fit all of the pixels.</p><pre>func createWorkersBuffered(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))</pre><pre>	type px struct{ x, y int }<br>	c := make(chan px, width*height)</pre><p>The rest of the function is exactly as the previous one.</p><p>Will this make our program faster? Let’s see!</p><pre>$ time ./mandelbrot<br>./mandelbrot  8.55s user 0.37s system 494% cpu 1.804 total</pre><p>It is much faster than before but still not nearly as fast as creating one goroutine per column.</p><p>The tracer shows that we still have some contention, and pprof quantifies it to 613ms.</p><pre>$ time ./mandelbrot &gt; workers-buf.trace<br>./mandelbrot &gt; workers-buf.trace  8.06s user 0.29s system 542% cpu 1.539 total</pre><pre>$ go tool trace workers-buf.trace<br>2017/10/23 12:04:51 Parsing trace...<br>2017/10/23 12:04:51 Serializing trace...<br>2017/10/23 12:04:51 Splitting trace...<br>2017/10/23 12:04:51 Opening browser</pre><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*xtGH621ycpDoarDn.png" /></figure><h3>Compromises</h3><p>Sending values through channels has a very low cost, but it does have a cost and we’re doing this over 4 million times in this program.</p><p>It seems like a good idea to limit this cost by creating fewer tasks. How can we even do that? Each task should be larger: let’s create a task per column.</p><pre>func createColWorkers(width, height int) image.Image {<br>	m := image.NewGray(image.Rect(0, 0, width, height))</pre><pre>	c := make(chan int)</pre><pre>	var w sync.WaitGroup<br>	for n := 0; n &lt; numWorkers; n++ {<br>		w.Add(1)<br>		go func() {<br>			for i := range c {<br>				for j := 0; j &lt; height; j++ {<br>					m.Set(i, j, pixel(i, j, width, height))<br>				}<br>			}<br>			w.Done()<br>		}()<br>	}</pre><pre>	for i := 0; i &lt; width; i++ {<br>		c &lt;- i<br>	}</pre><pre>	close(c)<br>	w.Wait()<br>	return m<br>}</pre><p>How much faster is this?</p><pre>$ time ./mandelbrot<br>./mandelbrot  4.72s user 0.04s system 495% cpu 0.962 total</pre><p>Pretty fast! And if we added a buffer to the channel, as shown in createColWorkersBuffered?</p><pre>$ time ./mandelbrot<br>./mandelbrot  4.74s user 0.04s system 513% cpu 0.931 total</pre><p>Just a tiny bit better.</p><h3>Conclusion</h3><p>So, it seems like creating one goroutine per column is the fastest option, but probably this changes given different image sizes. It is time to write benchmarks (they’re already written in the repo!), look at the traces and pprof data and make sensible and informed decisions.</p><p>We saw how pprof allows us to see how our program uses the CPU and how much locking contention exists. Pprof also provides a way to profile memory allocations which we didn’t cover. On the other side we saw the tracer, that allows us to have a very detailed view of what our program does, specially when our program doesn’t do much!</p><p>I hope you enjoyed this post, let me know what you think at <a href="https://twitter.com/francesc">@francesc</a> and subscribe to <a href="http://justforfunc.com/">#justforfunc</a> for more content every two weeks!</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c06bb3760507" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/using-the-go-execution-tracer-to-speed-up-fractal-rendering-c06bb3760507">Using the Go execution tracer to speed up fractal rendering</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[What’s the most common identifier in Go’s stdlib?]]></title>
            <link>https://medium.com/justforfunc/whats-the-most-common-identifier-in-go-s-stdlib-e468f3c9c7d9?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/e468f3c9c7d9</guid>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[justforfunc]]></category>
            <category><![CDATA[scanner]]></category>
            <category><![CDATA[programming]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:08:22 GMT</pubDate>
            <atom:updated>2018-02-12T17:50:37.110Z</atom:updated>
            <content:encoded><![CDATA[<p>This is the blog post form for the latest <a href="http://justforfunc.com/">justforfunc</a> episode of the same title. And the code for the program can be found <a href="https://github.com/campoy/justforfunc/blob/master/24-ast/scanner/main.go">here</a>, in the <a href="https://github.com/campoy/justforfunc">justforfunc repository</a>.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Fk23xhJoTbI4%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dk23xhJoTbI4&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Fk23xhJoTbI4%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/caf3a4f7f9265d7ec20f1f1937f0509e/href">https://medium.com/media/caf3a4f7f9265d7ec20f1f1937f0509e/href</a></iframe><h3>Problem statement</h3><p>Imagine you’ve been given this program below and you want to extract all of the identifiers in it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3044957964bdf14008e4747e73d31ca9/href">https://medium.com/media/3044957964bdf14008e4747e73d31ca9/href</a></iframe><p>We should obtain a list containing main, fmt, and Println.</p><h3>What is an identifier anyway?</h3><p>In order to answer this we need to go a bit into language theory. Just a bit, do not worry.</p><p>Programming languages are defined, among other things, by a series of rules of what is a valid program. These rules look something like:</p><pre>IfStmt = &quot;if&quot; [ SimpleStmt &quot;;&quot; ] Expression Block [ &quot;else&quot; ( IfStmt | Block ) ] .</pre><p>This rule tells us what an if statement looks like in Go. The &quot;if&quot;, &quot;;&quot;, and &quot;else&quot; pieces are keywords that help us figure out the structure of the program, while Expression Block, SimpleStmt, etc are other rules.</p><p>The set of these rules is called a language grammar. You can find all of them in the <a href="https://golang.org/ref/spec">Go language specification</a>.</p><p>These rules are not defined on the characters of the program, instead they’re defined on tokens. These tokens are atoms like if or else, but also slightly more complex kinds such as integers 42, floats 4.2, strings &quot;hello&quot;, or … identifiers like main.</p><p>But how do we know that main is an identifier and not a number? Well, there’s also rules for this. If you read the <a href="https://golang.org/ref/spec#identifier">identifiers</a> section of the Go specification, you’ll find this rule:</p><pre>identifier = letter { letter | unicode_digit } .</pre><p>In this rule, letter and unicode_digit do not represent tokens; they’re classes of characters. So given all of these rules, it is pretty straight-forward to write a program that goes character by character and each time it detects a group of them that matches a rule it just “emits” a token.</p><p>So if we start with: fmt.Println it would generate the tokens: fmt as an identifier, ., and Println as an identifier. Is this a function call? Well, at this point we do not know, and we do not care. The only structure is a sequence letting us in what order things appear.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/812/0*RPIALvOWCycadJbW.png" /><figcaption>Given a sequence of characters, a scanner generates a sequence of tokens.</figcaption></figure><p>This kind of program that given a sequence of characters generates a sequence of tokens is called a scanner. The Go standard library comes with a scanner for Go programs in go/scanner. The kinds of tokens it generates are defined in go/token.</p><h3>Using go/scanner</h3><p>Ok, so now that we understand what a scanner is. How do we use it?</p><h4>Reading arguments from the command line</h4><p>Let’s start with this simple program that simply prints all of the arguments given when executing it. We’ll go from there.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/4851b73d58fdc856136fcd087dfe31a3/href">https://medium.com/media/4851b73d58fdc856136fcd087dfe31a3/href</a></iframe><p>Next we need to scan every one of the files given as arguments. To do this we will need to create a new scanner.Scanner and initialize it with the contents of the file.</p><h4>Printing each token</h4><p>Before we can call the Init method in scanner.Scanner we will read the file contents and create a token.FileSet holding a token.File per file we scan.</p><p>Once the scanner has been initialized we can call Scan and print the token we obtain. Once we reach the end of the file scanned, we will obtain an EOF (End Of File) token.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/892eb4d5134dc8b4b5fc7a1788274493/href">https://medium.com/media/892eb4d5134dc8b4b5fc7a1788274493/href</a></iframe><h4>Counting tokens</h4><p>Great, so we’re able to print all tokens, but we need to keep track of how many times we see each identifier, sort them by how many times we saw them, and print the top 5.</p><p>In Go, the best way to do so is to use a map where the key will be the identifier, and the value how many times it’s been seen so far.</p><p>Each time we see an identifier, we need to increment its counter. Finally, at the end, we convert the map into a slice of pairs, which we can sort and print.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/119d770347189c520e6677b906c9b2c2/href">https://medium.com/media/119d770347189c520e6677b906c9b2c2/href</a></iframe><p>Some code has been removed for clarity, but the full source code can be found <a href="https://github.com/campoy/justforfunc/blob/master/24-ast/scanner/main.go">here</a>, in the <a href="https://github.com/campoy/justforfunc">justforfunc repository</a>.</p><h3>So what’s the most common identifier?</h3><p>Let’s run the program giving with the contents of github.com/golang/go.</p><pre>$ go install github.com/campoy/justforfunc/24-ast/scanner<br>$ scanner ~/go/src/**/*.go<br> 82163 v<br> 46584 err<br> 44681 Args<br> 43371 t<br> 37717 x</pre><p>Ok, so the most used identifier is v, talk about short identifiers! Let’s count only those identifiers that are three characters or longer, by modifying the code above a bit:</p><pre>for s, n := range counts {<br>	if len(s) &gt;= 3 {<br>		pairs = append(pairs, pair{s, n})<br>	}<br>}</pre><p>And run it again:</p><pre>$ go install github.com/campoy/justforfunc/24-ast/scanner<br>$ scanner ~/go/src/**/*.go<br> 46584 err<br> 44681 Args<br> 36738 nil<br> 25761 true<br> 21723 AddArg</pre><p>Nothing too surprising here, err and nil are present in basically every single program that does if err != nil. What about Args, though?</p><p>That’s a topic for a <a href="https://medium.com/justforfunc/understanding-go-programs-with-go-parser-c4e88a6edb87">next episode</a>.</p><p><a href="https://medium.com/justforfunc/understanding-go-programs-with-go-parser-c4e88a6edb87">Understanding Go programs with go/parser</a></p><h3>Thanks</h3><p>If you enjoyed this episode make sure you share it and subscribe to <a href="http://justforfunc.com/">justforfunc</a>! Also, consider sponsoring the series on <a href="https://patreon.com/justforfunc">patreon</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=e468f3c9c7d9" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/whats-the-most-common-identifier-in-go-s-stdlib-e468f3c9c7d9">What’s the most common identifier in Go’s stdlib?</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Understanding Go programs with go/parser]]></title>
            <link>https://medium.com/justforfunc/understanding-go-programs-with-go-parser-c4e88a6edb87?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/c4e88a6edb87</guid>
            <category><![CDATA[go]]></category>
            <category><![CDATA[parser]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[golang]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:08:10 GMT</pubDate>
            <atom:updated>2018-01-04T18:59:54.783Z</atom:updated>
            <content:encoded><![CDATA[<p>This blog post describes the same techniques used during <a href="https://www.youtube.com/watch?v=YRWCa84pykM">episode 25 of justforfunc</a> which you can watch right below.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FYRWCa84pykM%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DYRWCa84pykM&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FYRWCa84pykM%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/489d0637a8582958bdb3e1e4e81c690e/href">https://medium.com/media/489d0637a8582958bdb3e1e4e81c690e/href</a></iframe><h4>Previously in justforfunc</h4><p>In a <a href="https://medium.com/@francesc/whats-the-most-common-identifier-in-go-s-stdlib-e468f3c9c7d9">previous post</a>, we used the go/scanner package in Go’s standard library to identify which was the most common identifier in the standard library itself.</p><p><em>Spoiler alert</em>: it was v.</p><p>In order to get a somehow more meaningful list, we limited the search to those identifiers that were three letters long or more. This gave us err and nil, which we’ve all seen before in the (in)famous if err != nil { expression.</p><h4>Variables: package vs local</h4><p>What if I wanted to know which is the most common name for local variables? What about functions or types? In order to answer this question scanners fall short because they lack context. We know what tokens we saw before, but in order to know whether a var a = 3 is declared at package, function, or even block levels we need more context.</p><p>A package has many declarations, some of those declarations may be of functions which in time could declare local variables, constants, or even more functions!</p><p>But how do we find that structure from a sequence of tokens? Well, every single programming language has a set of rules that inform us on how to build such a tree from a sequence of tokens. This looks something like:</p><pre>VarDecl = <strong>&quot;var&quot;</strong> ( VarSpec | <strong>&quot;(&quot;</strong> { VarSpec <strong>&quot;;&quot;</strong> } <strong>&quot;)&quot;</strong> ) .<br>VarSpec = IdentifierList ( Type [ <strong>&quot;=&quot;</strong> ExpressionList ] | <strong>&quot;=&quot;</strong>  <br>                        ExpressionList ) .</pre><p>The rules above tell us that a VarDecl (variable declaration) starts with a var token, followed by either a VarSpec (variable specification) or a list of them surrounded by parentheses and separated by semicolons.</p><p><em>Note</em>: Those semicolons are actually added by the Go scanner, so you might not see them but the parser does.</p><p>If we start with a piece of Go code containing var a = 3, using go/scanner we could obtain the following list of tokens.</p><pre>[VAR], [IDENT &quot;a&quot;], [ASSIGN], [INT &quot;3&quot;], [SEMICOLON]</pre><p>The rules above help us figure out this is a VarDecl with only one VarSpec. Then we’ll parse an IdentifierList with a single Identifier a, no Type, and an ExpressionList with an Expression which is an integer with value 3.</p><p>Or, as a tree, it would look like the image below.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/942/0*STJNoHjXJBsnWB4x.png" /><figcaption>A tree structure made out of tokens.</figcaption></figure><p>The rules that allow us to go from a sequence of tokens to a tree structure form a <em>language grammar</em>, or syntax. The resulting tree is called an <em>Abstract Syntax Tree</em>, often simply <em>AST</em>.</p><h4>Using go/scanner</h4><p>Enough theory for now, let’s write some code! Let’s see how we can parse the expression var a = 3 and obtain an AST from it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/f8c29c8ea6ef28ae6311acb8a7b7bacb/href">https://medium.com/media/f8c29c8ea6ef28ae6311acb8a7b7bacb/href</a></iframe><p>This program compiles (yay!) but if you run you’ll see the following error:</p><pre>1:1: expected &#39;package&#39;, found &#39;var&#39; (and 1 more errors)</pre><p>Oh, yeah. In order to parse a declaration we are calling ParseFile, which expects a full Go file therefore starting with package before any other code (expect for comments).</p><p>If you were parsing an expression, such as 3 + 5 or other pieces of code which you could see as a value you could pass as a parameter, then you have ParseExpr, but that function will not help with a function declaration.</p><p>Let’s simply add package main at the beginning of our code and see the AST we obtain.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d840b0eb20821a15305984ca1368d070/href">https://medium.com/media/d840b0eb20821a15305984ca1368d070/href</a></iframe><p>And when we run it we get something a bit better … just a bit, though.</p><pre>$ go run main.go<br>&amp;{&lt;nil&gt; 1 main [0xc420054100] scope 0xc42000e210 {<br>        var a<br>}<br> [] [] []}</pre><p>Let’s print more detail by replacing the Println call by fmt.Printf(&quot;%#v&quot;, f) and try again.</p><pre>go run main.go<br>&amp;ast.File{Doc:(*ast.CommentGroup)(nil), Package:1, Name:(*ast.Ident)(0xc42000a060), Decls:[]ast.Decl{(*ast.GenDecl)(0xc420054100)}, Scope:(*ast.Scope)(0xc42000e210), Imports:[]*ast.ImportSpec(nil), Unresolved:[]*ast.Ident(nil), Comments:[]*ast.CommentGroup(nil)}</pre><p>Ok, that’s better but I’m too lazy to read this. Let’s import github.com/davecgh/go-spew/spew and use it to print an easier to read value.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/6e2d539a6aec0ad7f806c2ed4d0e64fd/href">https://medium.com/media/6e2d539a6aec0ad7f806c2ed4d0e64fd/href</a></iframe><p>Running this program shows us pretty much the same as before, but in a much more readable format.</p><pre>$ go run main.go<br>(*ast.File)(0xc42009c000)({<br> Doc: (*ast.CommentGroup)(&lt;nil&gt;),<br> Package: (token.Pos) 1,<br> Name: (*ast.Ident)(0xc42000a120)(main),<br> Decls: ([]ast.Decl) (len=1 cap=1) {<br>  (*ast.GenDecl)(0xc420054100)({<br>   Doc: (*ast.CommentGroup)(&lt;nil&gt;),<br>   TokPos: (token.Pos) 15,<br>   Tok: (token.Token) var,<br>   Lparen: (token.Pos) 0,<br>   Specs: ([]ast.Spec) (len=1 cap=1) {<br>    (*ast.ValueSpec)(0xc4200802d0)({<br>     Doc: (*ast.CommentGroup)(&lt;nil&gt;),<br>     Names: ([]*ast.Ident) (len=1 cap=1) {<br>      (*ast.Ident)(0xc42000a140)(a)<br>     },<br>     Type: (ast.Expr) &lt;nil&gt;,<br>     Values: ([]ast.Expr) (len=1 cap=1) {<br>      (*ast.BasicLit)(0xc42000a160)({<br>       ValuePos: (token.Pos) 23,<br>       Kind: (token.Token) INT,<br>       Value: (string) (len=1) &quot;3&quot;<br>      })<br>     },<br>     Comment: (*ast.CommentGroup)(&lt;nil&gt;)<br>    })<br>   },<br>   Rparen: (token.Pos) 0<br>  })<br> },<br> Scope: (*ast.Scope)(0xc42000e2b0)(scope 0xc42000e2b0 {<br>        var a<br>}<br>),<br> Imports: ([]*ast.ImportSpec) &lt;nil&gt;,<br> Unresolved: ([]*ast.Ident) &lt;nil&gt;,<br> Comments: ([]*ast.CommentGroup) &lt;nil&gt;<br>})</pre><p>I recommend spending some time actually reading this tree and seeing how each piece matches with the original code. Feel free to ignore Scope, Obj, and Unresolved as we’ll talk about those later on.</p><h4>Going from AST to code</h4><p>It is sometime useful to print an AST into the corresponding source code rather than its tree form. To do so, we have the go/printer package which you can easily use as a way to see what information is stored in the AST.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/7696a3cc291b9ff9982f5d1e78fcfb1a/href">https://medium.com/media/7696a3cc291b9ff9982f5d1e78fcfb1a/href</a></iframe><p>Executing this program prints the source code we parsed originally. It is now a good point to see how different values of the parsing mode affect what information is kept in the AST. Replace parser.AllErrors with parser.ImportsOnly or other possible values.</p><h4>Navigating the AST</h4><p>So far we have a tree that contains all of the information we want, but how do we extract the pieces of information we care about? This is where the go/ast package comes in handy (other than for declaring the ast.File that parser.ParseFile returns!).</p><p>Let’s use ast.Walk. This function receives two arguments. The second one is an ast.Node which is an interface satified by all the nodes in the AST. The first argument is an ast.Visitor which is also obviously an interface.</p><p>This interface has a single method.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d2648d6fe2ead29b5db456b6b6d385f3/href">https://medium.com/media/d2648d6fe2ead29b5db456b6b6d385f3/href</a></iframe><p>Ok, so we already have a node, since the ast.File returned by parser.ParseFile satisfies the interface, but we still need to create an ast.Visitor.</p><p>Let’s simply write one that prints the type of the node and returns itself.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e02f6b4c835d0030d7fce559c64b1716/href">https://medium.com/media/e02f6b4c835d0030d7fce559c64b1716/href</a></iframe><p>Running this program gives us a sequence of nodes, but we’ve lost the tree structure. Also, what are all of those nil nodes? Well, we should read the documentation of ast.Walk! Turns out the Visitor we return is used to visit each one of the children of the current node, and we end up by calling the Visitorwith a nil node as a way to communicate there’s no more nodes to visited.</p><p>Using that knowledge we can now print something that looks more like a tree.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/516236935c0ceee3ea8738da49147fe3/href">https://medium.com/media/516236935c0ceee3ea8738da49147fe3/href</a></iframe><p>The rest of the code in our program remains unchanged, and executing it prints this output:</p><pre>*ast.File<br>        *ast.Ident<br>        *ast.GenDecl<br>                *ast.ValueSpec<br>                        *ast.Ident<br>                        *ast.BasicLit</pre><h4>What’s the most common name per kind of identifier?</h4><p>Ok, so now that we understand how to parse code and visit its nodes, we are ready to extract the information we want: what are the most most common names for variables declared at package level vs those declared locally inside of a function.</p><p>We will start with a piece of code very similar to what we had in the previous episode, where we used go/scanner over a list of files passed as command line arguments.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/d773563c17f78998d03b2e68c0f16386/href">https://medium.com/media/d773563c17f78998d03b2e68c0f16386/href</a></iframe><p>Running this program will print the AST of each one of the files given as command line argument. You can try it on its own by running:</p><pre>$ go build -o parser main.go  &amp;&amp; parser main.go<br># output removed for brevity</pre><p>Let’s now change our visitor to keep track of how many times each identifier is used for each kind of variable declaration.</p><p>First let’s start by tracking all short variable declarations, since we know they are always local declarations.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/8a8815403580ef11ceca9535e591dfb7/href">https://medium.com/media/8a8815403580ef11ceca9535e591dfb7/href</a></iframe><p>For each assignment statement we’re checking whether the identifier name is _, which should be ignored, and whether this is the declaration point of the identifier. In order to do so we use the Obj field which keeps track of all the objects declared in a context.</p><p>If the Obj field is nil we know that the variable was declared in a different file, therefore it’s not a local variable declaration and we can ignore it.</p><p>If we run this program on the whole standard library we’ll see that the most common identifiers are:</p><pre>  7761 err<br>  6310 x<br>  5446 got<br>  4702 i<br>  3821 c</pre><p>Interestingly enough, v doesn’t appear at all! Are we missing any other ways of declaring local variables?</p><h3>Counting parameters and range variables too</h3><p>We’re missing a couple node types to have a more completely analysis of local variables. These are:</p><ul><li>function parameters, receivers, and named returned values.</li><li>range statements.</li></ul><p>Since the code to count a local variable identifier will be repeated all over let’s define a method on visitor instead.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/1fc08d0184e9cf4e311b2e3149388a53/href">https://medium.com/media/1fc08d0184e9cf4e311b2e3149388a53/href</a></iframe><p>For parameters and returned values we will have a list of identifiers. We also have the same for method receivers, even though they always have only one element. Let’s define an extra method for lists of identifiers.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bd4519254ab8c7f901168d46e0d74b51/href">https://medium.com/media/bd4519254ab8c7f901168d46e0d74b51/href</a></iframe><p>Then we can use that method for all the node types that might declare local variables.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/39c053d577e7e09b35f377396fd040fa/href">https://medium.com/media/39c053d577e7e09b35f377396fd040fa/href</a></iframe><p>Great, let’s run this and see which one is the most common local variable name for now!</p><pre>$ ./parser ~/go/src/**/*.go<br>most common local variable names<br> 12264 err<br>  9395 t<br>  9163 x<br>  7442 i<br>  6127 c</pre><h4>Handling var declarations</h4><p>Let’s move into handling the var declarations. These are more interesting because they could be local or global, and the only way to know is to check whether they’re at the ast.File level.</p><p>To do so we’re going to create a new visitor per file which will keep track of the declarations that are global, so we can count the identifiers correctly.</p><p>To do so we’ll add a pkgDecls field of type map[*ast.GenDecl]bool in our visitor, and it will be initialized by a newVisitor function. We’ll also add a globals field tracking how many times an identifier has been declared.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/dc413b13b543a89aaeddee3287640eb6/href">https://medium.com/media/dc413b13b543a89aaeddee3287640eb6/href</a></iframe><p>Our main program will need to create a new visitor per file and keep track of the total results.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3ba989b9f30b3e078ff2e255f01611f4/href">https://medium.com/media/3ba989b9f30b3e078ff2e255f01611f4/href</a></iframe><p>Ok, we just have one more piece of the puzzle to complete. We need to track the *ast.GenDecl nodes and find all the variable declarations in them.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/c8bbb792cec8348105b331b544a83b59/href">https://medium.com/media/c8bbb792cec8348105b331b544a83b59/href</a></iframe><p>For each declaration we will only count those that start with a token.VAR, therefore ignoring constants, types, and other kind of identifiers. Then, for each value declared, we’ll check whether it’s a global or local declaration, and count them accordingly and ignoring _.</p><p>The whole program is available <a href="https://github.com/campoy/justforfunc/blob/master/25-go-parser/main.go">here</a>.</p><p>Executing the program will give us this result:</p><pre>$ ./parser ~/go/src/**/*.go<br>most common local variable names<br> 12565 err<br>  9876 x<br>  9464 t<br>  7554 i<br>  6226 b<br>most common global variable names<br>    29 errors<br>    28 signals<br>    23 failed<br>    15 tests<br>    12 debug</pre><p>So there you go, the most common local variable name is err, while the most common package variable name is errors.</p><p>Which one is the most common constant name? How would you find it?</p><h4>Thanks</h4><p>If you enjoyed this episode make sure you share it and subscribe to <a href="http://justforfunc.com/">justforfunc</a> and follow me on <a href="http://medium.com/@francesc">Medium</a> or <a href="http://twitter.com/francesc">twitter</a>! Also, consider sponsoring the series on <a href="https://patreon.com/justforfunc">patreon</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=c4e88a6edb87" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/understanding-go-programs-with-go-parser-c4e88a6edb87">Understanding Go programs with go/parser</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[The justforfunc 2017 top 5]]></title>
            <link>https://medium.com/justforfunc/justforfunc-a-year-in-review-af4003d56179?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/af4003d56179</guid>
            <category><![CDATA[justforfunc]]></category>
            <category><![CDATA[top-5]]></category>
            <category><![CDATA[year-in-review]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[youtube]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:07:59 GMT</pubDate>
            <atom:updated>2018-01-11T18:05:34.578Z</atom:updated>
            <content:encoded><![CDATA[<p>I was just checking the stats on the justforfunc channel and … whoa over 4 years of watch time during 2017! That means there’s been four people continuously watching my videos for a whole year.</p><p>To those four incredibly dedicated fans, huge thanks and … are you OK?</p><p>Anyway, I thought it would be a good moment to see how the channel has evolved during 2017 and what videos have been the most successful.</p><h3>First some stats</h3><p>The channel is doing great. We recently passed 10k subscribers (which I celebrated with <a href="https://www.youtube.com/watch?v=kuted8F2KJw">this video</a>) and the number keeps growing! Look at these numbers, stat!</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*W3UrkC8Ue0IVW1J7xOlcjg.png" /></figure><p>So without any more ado, let’s go with the top five videos of 2017!</p><h4>#5: Unit Testing HTTP servers</h4><p>This video was a fun one to do and I think it’s been very successful because it covers something people care about.</p><p>Testing HTTP servers is not necessarily easy and most people have no idea on how to use <a href="https://golang.org/pkg/net/http/httptest/#ResponseRecorder">http.ResponseRecorder</a> or even that it exists!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FhVFEV-ieeew%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DhVFEV-ieeew&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FhVFEV-ieeew%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/07dd1ec70581b7b410dd3859f398a8c5/href">https://medium.com/media/07dd1ec70581b7b410dd3859f398a8c5/href</a></iframe><h4>#4: Flappy Gopher</h4><p>The first episode of a series of three videos that I started after attending GoLab.io in Florence early 2017. Why was this one successful? I mean … it shows you how to develop a Flappy Bird clone in Go!</p><p>The best thing of this episode is that I got many people sending me messages sharing their own projects. And the code was used in a program to teach children Go.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FaYkxFbd6luY%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DaYkxFbd6luY&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FaYkxFbd6luY%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/0c133c62e014bf3a4089313d4b360098/href">https://medium.com/media/0c133c62e014bf3a4089313d4b360098/href</a></iframe><h4>#3 A Text to Speech server with gRPC and Kubernetes</h4><p>Was this episode the answer to “how many buzzwords can you include in a title”? We’ll never know … well, you’ll never know!</p><p>But the result is a fun video where I develop a distributed version of the <strong>say</strong> command available on Mac, using flite, Docker, Kubernetes, Go, and all of the other things cool kids do.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FXaMr--wAuSI%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DXaMr--wAuSI&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FXaMr--wAuSI%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/f8b6581a9d1e8cfda4f1f270a7dc37f7/href">https://medium.com/media/f8b6581a9d1e8cfda4f1f270a7dc37f7/href</a></iframe><h4>#2 The Context Package</h4><p>I’ve received so many notes regarding this episode. Many many people tell me it’s the clearest introduction to the context package they’ve ever seen.</p><p>Maybe it’s because this episode was the result of a talk I gave four times before? Probably, but I want to believe it’s because I’m wearing the coolest t-shirt I own.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FLSzR0VEraWw%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DLSzR0VEraWw&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FLSzR0VEraWw%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/97ef00cf73b33f28426557310bed6982/href">https://medium.com/media/97ef00cf73b33f28426557310bed6982/href</a></iframe><p>And last and definitely not least (because we’re counting down, so …)</p><h4>#1 Go Tooling in Action</h4><p>This video is the one that inspired me to create the channel. Its success is not really surprising as I keep on building on it by developing a <a href="http://github.com/campoy/go-tooling-workshop">full day workshop</a> based on the materials I once developed for GOTO Chicago.</p><p>The video is so old that it doesn’t even have the justforfunc branding, since it didn’t exist yet!</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2FuBjoTxosSys%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DuBjoTxosSys&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2FuBjoTxosSys%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="640" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/f41cfea665bcf386ee6b2bc402c1cee8/href">https://medium.com/media/f41cfea665bcf386ee6b2bc402c1cee8/href</a></iframe><h4>What’s your favorite?</h4><p>So what’s your favorite episode? Is it on this list or maybe it’s another one of the 26 episodes I’ve released so far!</p><p>Let me know on <a href="https://twitter.com/francesc">twitter</a> @francesc and send any feedback or suggestions for the channel to form.justforfunc.com.</p><h4>Thanks (and super thanks to my patrons!)</h4><p>Thanks to all the subscribers for an amazing 2017, and to my patrons for allowing me to improve the recording material (now that I don’t work for Google anymore).</p><p>You can become one of my patrons on <a href="http://patreon.com/justforfunc">patreon.com/justforfunc</a>, and in exchange you’ll have my eternal gratitude!</p><figure><a href="https://patreon.com/justforfunc"><img alt="" src="https://cdn-images-1.medium.com/max/1024/1*lNCuxnrgfApvIIcYRVKdKA.png" /></a><figcaption><a href="https://patreon.com/justforfunc">https://patreon.com/justforfunc</a></figcaption></figure><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=af4003d56179" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/justforfunc-a-year-in-review-af4003d56179">The justforfunc 2017 top 5</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
        <item>
            <title><![CDATA[Why are there nil channels in Go?]]></title>
            <link>https://medium.com/justforfunc/why-are-there-nil-channels-in-go-9877cc0b2308?source=rss----7dad93227ded---4</link>
            <guid isPermaLink="false">https://medium.com/p/9877cc0b2308</guid>
            <category><![CDATA[tutorial]]></category>
            <category><![CDATA[golang]]></category>
            <category><![CDATA[programming]]></category>
            <category><![CDATA[channel]]></category>
            <category><![CDATA[justforfunc]]></category>
            <dc:creator><![CDATA[Francesc Campoy]]></dc:creator>
            <pubDate>Mon, 15 Jan 2018 19:07:45 GMT</pubDate>
            <atom:updated>2018-02-12T17:49:04.574Z</atom:updated>
            <content:encoded><![CDATA[<h4>A practical example</h4><p>This blog post is complementary to <a href="https://www.youtube.com/watch?v=t9bEg2A4jsw">episode 26 of justforfunc</a> which you can watch right below.</p><iframe src="https://cdn.embedly.com/widgets/media.html?src=https%3A%2F%2Fwww.youtube.com%2Fembed%2Ft9bEg2A4jsw%3Ffeature%3Doembed&amp;url=http%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3Dt9bEg2A4jsw&amp;image=https%3A%2F%2Fi.ytimg.com%2Fvi%2Ft9bEg2A4jsw%2Fhqdefault.jpg&amp;key=a19fcc184b9711e1b4764040d3dc5c07&amp;type=text%2Fhtml&amp;schema=youtube" width="854" height="480" frameborder="0" scrolling="no"><a href="https://medium.com/media/b9c3f645a8a4be76235ca20033440ebb/href">https://medium.com/media/b9c3f645a8a4be76235ca20033440ebb/href</a></iframe><p>Everybody that has written some Go knows about channels. Most of us also know that the default value for channels is nil. But not many of us know that this nil value is actually useful.</p><p>I got this same question on <a href="https://twitter.com/francesc">twitter</a>, from a developer learning Go, wondering whether Go nil channels existed just for completeness.</p><p>It does makes sense to wonder whether they’re useful, as their behavior seems to indicate otherwise.</p><p>Given a nil channel c:</p><ul><li>&lt;-c receiving from c blocks forever</li><li>c &lt;- v sending into c blocks forever</li><li>close(c) closing c panics</li></ul><p>But I still insist they are useful. Let me introduce a problem whose solution seems obvious at first, but it is actually not as easy as one might think and actually benefits from nil channels.</p><h3>Merging channels</h3><p>Your mission, should you choose to accept it, is to write a function that given two channels a and b of some type returns one channel c of the same type. Every element received in a or b will be sent to c, and once both a and b are closed c will be closed too.</p><figure><img alt="" src="https://cdn-images-1.medium.com/max/1024/0*aKHj7JJ0UCDEYu23.png" /></figure><h3>An auxiliary function</h3><p>Before we start, let’s write a function that will help us test our solution. This function returns a channel that will eventually receive, at random intervals, all of the given values and finish by being closed.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/383641af3734230100b885710febb95b/href">https://medium.com/media/383641af3734230100b885710febb95b/href</a></iframe><p>This function creates a channel, starts a new go routine that sends values to the created channel, and finally returns the channel.</p><p>This is pretty common pattern when dealing with channels, so make sure you understand how it works before you continue reading.</p><h3>Let’s get started</h3><p>Since we don’t really have a preference over a or b we’re going to avoid creating a preference by choosing on which channel we should range first. Let’s instead keep the symmetry and use an infinite loop and select over both channels.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/bee18364a88d170ff6b6a70622757653/href">https://medium.com/media/bee18364a88d170ff6b6a70622757653/href</a></iframe><p>This looks pretty good, let’s write a quick test and run it.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e27602d04e133b4696d4af1acd9ee753/href">https://medium.com/media/e27602d04e133b4696d4af1acd9ee753/href</a></iframe><p>This should print 1 to 8 in some order and end successfully. Let’s see what happens.</p><pre>&gt; go run main.go<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>0<br>0<br>0<br>0<br>0<br>0<br>0<br>😱</pre><p>Ok, so clearly this is not good because the program doesn’t ever finish. Once it has printed the values from 1 to 8 it starts printing zeros forever.</p><h3>Handling closed channels</h3><p>What happens when we receive from a closed channel? We get the default value of the type of the channel. In our case, the type is int so the value is 0.</p><p>We could check for channels being closed by comparing to zero, but what if one of the values we received was a zero? Instead we can use the “value comma ok” syntax:</p><pre>v, ok := &lt;- c</pre><p>When using this syntax ok is a boolean that will be true for as long the channel is open. Knowing this we can avoid sending superfluous zeros into c.</p><p>We should also stop iterating at some point … so let’s keep track of when both channels are closed too.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/3653b4bfc354b66bfab4033e42062948/href">https://medium.com/media/3653b4bfc354b66bfab4033e42062948/href</a></iframe><p>This looks like it might work! Let’s run it.</p><pre>&gt; go run main.go<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>fatal error: all goroutines are asleep - deadlock!</pre><pre>goroutine 1 [chan receive]:<br>main.main()<br>        /Users/francesc/src/github.com/campoy/campoy.cat/site/static/code/nilchans/main.go:13 +0x186<br>exit status 2</pre><p>Ooops, we forgot something. What could that be? Well, we can see that there’s only one go routine running and it’s blocked on line 13. That line is:</p><pre>for v := range c {</pre><p>Can you see what the problem is? Well, a range statement iterates over all the values in a channel until the channel is closed. But who is closing the channel?</p><p>We forgot! Let’s add a defer statement in our go routine to make sure the channel is closed eventually.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/99b6e8080e35de5c8207174e77276247/href">https://medium.com/media/99b6e8080e35de5c8207174e77276247/href</a></iframe><p>Note that the defer statement is inside of the anonymous function called in a new go routine, rather than inside of merge. Otherwise c would be closed as soon as we exited merge and sending a value into it would panic.</p><p>Let’s run it and see what happens.</p><pre>&gt; go run main.go<br>1<br>2<br>3<br>4<br>5<br>6<br>7<br>8</pre><p>This looks great … but is it?</p><h3>Busy loops</h3><p>The code we wrote so far is pretty good. It is functionally correct, but if you deployed this in production you might end up running into performance troubles.</p><p>In order to show you where the problem is, let’s add a bit of logging.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/e1236b98b1bb8dd5f0291eff990aa082/href">https://medium.com/media/e1236b98b1bb8dd5f0291eff990aa082/href</a></iframe><p>Let’s run it and see what happens.</p><pre>&gt; go run main.go<br>2<br>3<br>4<br>5<br>6<br>7<br>8<br>a is done<br>2018/01/14 20:47:22 b is done<br>... 😱<br>2018/01/14 20:47:23 b is done<br>2018/01/14 20:47:23 a is done</pre><p>Uh oh! It seems once a channel is done we keep on iterating non-stop!</p><p>It does make sense after all. As we saw at the beginning reading from a closed channel never blocks. Therefore the select statement will block as long as both channels are open until a new element is ready, but once one of them closes we will iterate and waste CPU. This is also known as a busy loop, and it’s not good.</p><h3>Disabling a case in a select statement</h3><p>In order to avoid the busy loop describe previously we would like to disable a part of the selectstatement. Concretely, we’d like to remove case v, ok := &lt;- a when a is closed and similarly for b. But how?</p><p>As we mentioned at the beginning, receiving from a nil channels blocks forever. So to disable a casereceiving from a channel, we can simply set that channel to nil!</p><p>We can then stop using adone and bdone and instead check for a and b being nil.</p><iframe src="" width="0" height="0" frameborder="0" scrolling="no"><a href="https://medium.com/media/5ca8efe1113e28708cceca4ef530b519/href">https://medium.com/media/5ca8efe1113e28708cceca4ef530b519/href</a></iframe><p>Ok, hopefully this will avoid unnecessary loops. Let’s try it.</p><pre>&gt; go run main.go<br>2<br>1<br>4<br>3<br>6<br>5<br>8<br>7<br>b is <strong>done</strong><br>a is <strong>done</strong></pre><p>The code for the final solution is on <a href="https://github.com/campoy/justforfunc/blob/master/26-nil-chans/main.go">GitHub</a>.</p><h3>Victory!</h3><p>This is just one of the many concurrency patterns that can benefit from nil channels. Have you used nil channels to solve some other problems? Share your story! You can get in touch with me on <a href="https://twitter.com/francesc">twitter</a> or simply dropping a comment here.</p><p>And you might wonder … how dow e merge more than two channels?<br>Well, wonder no more and go read the <a href="https://medium.com/justforfunc/two-ways-of-merging-n-channels-in-go-43c0b57cd1de">next episode</a> that covers exactly that!</p><p><a href="https://medium.com/justforfunc/two-ways-of-merging-n-channels-in-go-43c0b57cd1de">Two ways of merging N channels in Go</a></p><p>If you enjoyed this episode make sure you share it and subscribe to <a href="http://justforfunc.com/">justforfunc</a>! Also, consider sponsoring the series on <a href="https://patreon.com/justforfunc">patreon</a>.</p><img src="https://medium.com/_/stat?event=post.clientViewed&referrerSource=full_rss&postId=9877cc0b2308" width="1" height="1" alt=""><hr><p><a href="https://medium.com/justforfunc/why-are-there-nil-channels-in-go-9877cc0b2308">Why are there nil channels in Go?</a> was originally published in <a href="https://medium.com/justforfunc">justforfunc</a> on Medium, where people are continuing the conversation by highlighting and responding to this story.</p>]]></content:encoded>
        </item>
    </channel>
</rss>