<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0"><channel><title>Sylvain Wallez</title><link>http://bluxte.net/</link><description>Random musings of a busy geek</description><lastBuildDate>Sun, 08 Jan 2023 16:34:57 +0100</lastBuildDate><item><title>Getting meaningful stack traces from Rust tests returning a Result</title><link>http://bluxte.net/musings/2023/01/08/improving_failure_messages_rust_tests/</link><description>&lt;p&gt;I was recently writing a test for a side project (more on that in a future post), which looked like this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cp"&gt;#[test]&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="k"&gt;fn&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;test_render_index_page&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;-&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;anyhow&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="nb"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;read_to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;tests/data/gdoc/index.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;serde_json&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="kd"&gt;let&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;gdocs2hugo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;gdoc_to_html&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="n"&gt;insta&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;assert_snapshot&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;convert_test&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;&lt;span class="w"&gt; &lt;/span&gt;&lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;

&lt;span class="w"&gt;    &lt;/span&gt;&lt;span class="nb"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;&lt;span class="w"&gt;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The test returns an &lt;a href="https://docs.rs/anyhow/latest/anyhow/type.Result.html"&gt;anyhow::Result&lt;/a&gt; that can capture the various error types returned by any of the first 3 lines.&lt;/p&gt;
&lt;p&gt;Now what happens if one of those lines returns a failed result? For example when &lt;code&gt;index.json&lt;/code&gt; doesn’t exist:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test_render_index_page&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;FAILED&lt;/span&gt;

&lt;span class="n"&gt;failures&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="o"&gt;----&lt;/span&gt; &lt;span class="n"&gt;test_render_index_page&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;----&lt;/span&gt;
&lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test_render_index_page&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;panicked&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;assertion failed: `(left == right)`&lt;/span&gt;
&lt;span class="s1"&gt;  left: `1`,&lt;/span&gt;
&lt;span class="s1"&gt; right: `0`: the test returned a termination value with a non-zero status code (1) which indicates a failure&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/test/src/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;184&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;RUST_BACKTRACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="n"&gt;environment&lt;/span&gt; &lt;span class="n"&gt;variable&lt;/span&gt; &lt;span class="n"&gt;to&lt;/span&gt; &lt;span class="n"&gt;display&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;backtrace&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We know that some file wasn’t found, causing the &lt;code&gt;test_render_index_page&lt;/code&gt; test to fail. In this simple example we only have one line that can cause this error, but in more complex tests we may open several files and the test result will not be helpful to determine which is the faulty one.&lt;/p&gt;
&lt;p&gt;Also the panic message is about a failed assertion and not about our missing file. That error is output to stdout, which is output early in the test output and is easy to miss when you have lots of tests.&lt;/p&gt;
&lt;p&gt;Side note: I wish Rust included the file name in this error, which would make it much more useful. I assume the reason is that it would require allocating a string to copy the path so that it’s owned by the Error object. We certainly don’t want to allocate memory every time we test if a file exists!&lt;/p&gt;
&lt;p&gt;Let’s see if &lt;code&gt;RUST_BACKTRACE=1&lt;/code&gt; is more helpful:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;No&lt;/span&gt; &lt;span class="n"&gt;such&lt;/span&gt; &lt;span class="n"&gt;file&lt;/span&gt; &lt;span class="n"&gt;or&lt;/span&gt; &lt;span class="n"&gt;directory&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
&lt;span class="n"&gt;test&lt;/span&gt; &lt;span class="n"&gt;test_render_index_page&lt;/span&gt; &lt;span class="o"&gt;...&lt;/span&gt; &lt;span class="n"&gt;FAILED&lt;/span&gt;

&lt;span class="n"&gt;failures&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;

&lt;span class="o"&gt;----&lt;/span&gt; &lt;span class="n"&gt;test_render_index_page&lt;/span&gt; &lt;span class="n"&gt;stdout&lt;/span&gt; &lt;span class="o"&gt;----&lt;/span&gt;
&lt;span class="n"&gt;thread&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;test_render_index_page&amp;#39;&lt;/span&gt; &lt;span class="n"&gt;panicked&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="s1"&gt;&amp;#39;assertion failed: `(left == right)`&lt;/span&gt;
&lt;span class="s1"&gt;  left: `1`,&lt;/span&gt;
&lt;span class="s1"&gt; right: `0`: the test returned a termination value with a non-zero status code (1) which indicates a failure&amp;#39;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/test/src/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;184&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;stack&lt;/span&gt; &lt;span class="n"&gt;backtrace&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
   &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;rust_begin_unwind&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/std/src/&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;584&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
   &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;panic_fmt&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;142&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;14&lt;/span&gt;
   &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;assert_failed_inner&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;218&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;23&lt;/span&gt;
   &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;assert_failed&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/&lt;/span&gt;&lt;span class="n"&gt;panicking&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;181&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
   &lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;test&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;assert_test_result&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/test/src/&lt;/span&gt;&lt;span class="n"&gt;lib&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;184&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
   &lt;span class="mi"&gt;5&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;publish_test&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;test_render_index_page&lt;/span&gt;&lt;span class="o"&gt;::{{&lt;/span&gt;&lt;span class="n"&gt;closure&lt;/span&gt;&lt;span class="o"&gt;}}&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="o"&gt;./&lt;/span&gt;&lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;publish_test&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;
   &lt;span class="mi"&gt;6&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FnOnce&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;call_once&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;248&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
   &lt;span class="mi"&gt;7&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;core&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;ops&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;FnOnce&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;call_once&lt;/span&gt;
             &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="sr"&gt;/rustc/897e37553bba8b42751c67658967889d11ecd120/library/core/src/ops/&lt;/span&gt;&lt;span class="kd"&gt;function&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;rs&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;248&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="mi"&gt;5&lt;/span&gt;
&lt;span class="n"&gt;note&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Some&lt;/span&gt; &lt;span class="n"&gt;details&lt;/span&gt; &lt;span class="n"&gt;are&lt;/span&gt; &lt;span class="n"&gt;omitted&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt; &lt;span class="k"&gt;with&lt;/span&gt; &lt;span class="err"&gt;`&lt;/span&gt;&lt;span class="n"&gt;RUST_BACKTRACE&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;&lt;span class="n"&gt;full&lt;/span&gt;&lt;span class="err"&gt;`&lt;/span&gt; &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;verbose&lt;/span&gt; &lt;span class="n"&gt;backtrace&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The only line in our code is &lt;code&gt;./tests/publish_test.rs:2:1&lt;/code&gt; which is the function declaration. But we knew that already…&lt;/p&gt;
&lt;p&gt;We could replace every &lt;code&gt;?&lt;/code&gt; operator with &lt;code&gt;unwrap()&lt;/code&gt; to panic early and have a meaningful location in the panic message, but that’s a lot of additional typing and it obscures the code. Also a good practice is to avoid &lt;code&gt;unwrap()&lt;/code&gt; unless the result can never be an error to avoid panics, so we don’t want to introduce the cognitive dissonance of avoiding &lt;code&gt;unwrap()&lt;/code&gt; in regular code while expecting its use in tests.&lt;/p&gt;
&lt;h2 id="testerror-an-error-type-that-panics-early"&gt;TestError: an error type that panics early&lt;/h2&gt;
&lt;p&gt;To make the stack trace more informative, we can use a little trick by panicking not in the test runner, but at the location where a &lt;code&gt;?&lt;/code&gt; causes the test to exit with an error. To achieve that we should remember that the &lt;code&gt;?&lt;/code&gt; operator &lt;a href="https://doc.rust-lang.org/reference/expressions/operator-expr.html#the-question-mark-operator"&gt;is syntactic sugar&lt;/a&gt; for:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;if let Error(err) = result { return Result::Err(From::from(err)) }
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;&lt;code&gt;From&lt;/code&gt; above will resolve to the error variant of the test function return value. If the call to &lt;code&gt;From::from&lt;/code&gt; panics, we will have an informative stacktrace.&lt;/p&gt;
&lt;p&gt;So let’s replace &lt;code&gt;anyhow::Result&amp;lt;()&amp;gt;&lt;/code&gt; with &lt;code&gt;TestResult&lt;/code&gt; defined as follows:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;derive&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Debug&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;enum&lt;/span&gt; &lt;span class="nt"&gt;TestError&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="nt"&gt;impl&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="nt"&gt;std&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;:fmt&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="nd"&gt;:Display&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;From&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="nt"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;for&lt;/span&gt; &lt;span class="nt"&gt;TestError&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;track_caller&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;
    &lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;-&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;Self&lt;/span&gt; &lt;span class="err"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;panic&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;error: {}: {}&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;any&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;type_name&lt;/span&gt;&lt;span class="o"&gt;::&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="err"&gt;}&lt;/span&gt;

&lt;span class="nt"&gt;type&lt;/span&gt; &lt;span class="nt"&gt;TestResult&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nt"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;(),&lt;/span&gt; &lt;span class="nt"&gt;TestError&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;;&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;If a &lt;code&gt;?&lt;/code&gt; operator is run with an error, &lt;code&gt;TestError::from&lt;/code&gt; will panic. The &lt;code&gt;&lt;a href="https://doc.rust-lang.org/reference/attributes/codegen.html#the-track_caller-attribute"&gt;track_caller&lt;/a&gt;&lt;/code&gt; attribute makes sure the panic will output the location of the caller (our test code) instead of the location of &lt;code&gt;TestError::from&lt;/code&gt; which isn’t informative.&lt;/p&gt;
&lt;p&gt;We can now use it as the result of our test function:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="cp"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;test&lt;/span&gt;&lt;span class="cp"&gt;]&lt;/span&gt;
&lt;span class="nt"&gt;fn&lt;/span&gt; &lt;span class="nt"&gt;test_render_index_page&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="nt"&gt;-&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="nt"&gt;TestResult&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;

    &lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;json&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;fs&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;read_to_string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;tests/data/gdoc/index.json&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;doc&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;serde_json&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from_str&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;json&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="n"&gt;let&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;gdocs2hugo&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;gdoc_to_html&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;render&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;doc&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;?&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

    &lt;span class="n"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Result&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Err&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;From&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;from&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;std&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;io&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;last_os_error&lt;/span&gt;&lt;span class="p"&gt;()));&lt;/span&gt;
    &lt;span class="n"&gt;insta&lt;/span&gt;&lt;span class="o"&gt;::&lt;/span&gt;&lt;span class="n"&gt;assert_snapshot&lt;/span&gt;&lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s2"&gt;&amp;quot;index_page&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;html&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="n"&gt;Ok&lt;/span&gt;&lt;span class="p"&gt;(())&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This results in the following stack trace:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;test test_render_index_page ... FAILED

failures:

---- test_render_index_page stdout ----
thread &amp;#39;test_render_index_page&amp;#39; panicked at &amp;#39;error: std::io::error::Error - No such file or directory (os error 2)&amp;#39;, tests/publish_test.rs:4:16
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Yay 🎉! That’s a lot better! The panic message gives us the error type, its message, and the exact location where it happened in the test code! And we no more have this split output where the real error message is away from the panic message.&lt;/p&gt;
&lt;h2 id="publishing-testerror-on-cratesio"&gt;Publishing TestError on crates.io&lt;/h2&gt;
&lt;p&gt;Although &lt;code&gt;TestResult&lt;/code&gt; is very small, it’s pretty useful and deserves to be published on &lt;a href="https://crates.io/"&gt;crates.io&lt;/a&gt;. We should &lt;a href="https://rust-unofficial.github.io/patterns/patterns/structural/small-crates.html"&gt;prefer small crates&lt;/a&gt;, after all! Looking at how to name the crate, I discovered that…  &lt;a href="https://crates.io/crates/testresult"&gt;there was already a crate for that&lt;/a&gt; 😮! It even has the exact same &lt;code&gt;TestResult&lt;/code&gt; type! I should have looked there first 😕&lt;/p&gt;
&lt;p&gt;However my version is a bit more elaborate:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;it accepts any kind of error, even those not implementing &lt;code&gt;std::error::Error&lt;/code&gt; (&lt;code&gt;anyhow::Error&lt;/code&gt; &lt;a href="https://github.com/dtolnay/anyhow/issues/25"&gt;is one of them&lt;/a&gt;!)&lt;/li&gt;
&lt;li&gt;the use of &lt;code&gt;track_caller&lt;/code&gt; provides a more useful panic message&lt;/li&gt;
&lt;li&gt;the panic message also contains the error type&lt;/li&gt;
&lt;li&gt;&lt;code&gt;TestError&lt;/code&gt; being an empty enum, it cannot be instantiated, so this prevents its use for anything else than implicit error conversion.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So I ended up packaging these changes as a &lt;a href="https://github.com/wiktor-k/testresult/pull/3"&gt;PR for the existing crate&lt;/a&gt;. The maintainer liked it and promptly included it in a new release! So use the &lt;code&gt;testresult&lt;/code&gt; crate to improve your test reports!&lt;/p&gt;
&lt;p&gt;Happy testing!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Sun, 08 Jan 2023 16:34:57 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2023-01-08:musings/2023/01/08/improving_failure_messages_rust_tests/</guid></item><item><title>'Go: the Good, the Bad and the Ugly'</title><link>http://bluxte.net/musings/2018/04/10/go-good-bad-ugly/</link><description>&lt;p&gt;This is an additional post in the “&lt;a href="https://github.com/ksimka/go-is-not-good"&gt;Go is not good&lt;/a&gt;” series. Go does have some nice features, hence the “The Good” part in this post, but overall I find it cumbersome and painful to use when we go beyond API or network servers (which is what it was designed for) and use it for business domain logic. But even for network programming, it has a lot of gotchas both in its design and implementation that make it dangerous under an apparent simplicity.&lt;/p&gt;
&lt;p&gt;What motivated this post is that I recently came back to using Go for a side project. I used Go extensively in my previous job to write a network proxy (both http and raw tcp) for a SaaS service. The network part was rather pleasant (I was also discovering the language), but the accounting and billing part that came with it was painful. As my side project was a simple API I thought using Go would be the right tool to get the job done quickly, but as we know many projects grow beyond their initial scope, so I had to write some data processing to compute statistics and the pains of Go came back. So here's my take on Go woes.&lt;/p&gt;
&lt;p&gt;Some background: I love statically typed languages. My first significant programs were written in &lt;a href="https://en.wikipedia.org/wiki/Pascal_(programming_language)"&gt;Pascal&lt;/a&gt;. I then used &lt;a href="https://en.wikipedia.org/wiki/Ada_(programming_language)"&gt;Ada&lt;/a&gt; and C/C++ when I started working in the early 90's. I later moved to Java and finally Scala (with some Go in between) and recently started learning &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt;. I've also written a substantial amount of JavaScript, because up to recently it was the only language available in web browsers. I feel insecure with dynamically typed languages and try to limit their use to simple scripting. I'm comfortable with imperative, functional and object oriented approaches.&lt;/p&gt;
&lt;p&gt;This is a long post, so here's the menu to whet your appetite:&lt;/p&gt;
&lt;div class="toc"&gt;
&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-good"&gt;The Good&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#go-is-easy-to-learn"&gt;Go is easy to learn&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#easy-concurrent-programming-with-goroutines-and-channels"&gt;Easy concurrent programming with goroutines and channels&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#great-standard-library"&gt;Great standard library&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#go-is-performant"&gt;Go is performant&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#language-defined-source-code-format"&gt;Language defined source code format&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#standardized-test-framework"&gt;Standardized test framework&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#go-programs-are-great-for-operations"&gt;Go programs are great for operations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#defer-statement-to-avoid-forgetting-to-clean-up"&gt;Defer statement, to avoid forgetting to clean up&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#new-types"&gt;New types&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-bad"&gt;The Bad&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#go-ignored-advances-in-modern-language-design"&gt;Go ignored advances in modern language design&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#interfaces-are-structural-types"&gt;Interfaces are structural types&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#interface-methods-dont-support-default-implementations"&gt;Interface methods don't support default implementations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#no-enumerations"&gt;No enumerations&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-var-dilemma"&gt;The := / var dilemma&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#zero-values-that-panic"&gt;Zero values that panic&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#go-doesnt-have-exceptions-oh-wait-it-does"&gt;Go doesn't have exceptions. Oh wait... it does!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#the-ugly"&gt;The Ugly&lt;/a&gt;&lt;ul&gt;
&lt;li&gt;&lt;a href="#the-dependency-management-nightmare"&gt;The dependency management nightmare&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#mutability-is-hardcoded-in-the-language"&gt;Mutability is hardcoded in the language&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#slice-gotchas"&gt;Slice gotchas&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#mutability-and-channels-race-conditions-made-easy"&gt;Mutability and channels: race conditions made easy&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#noisy-error-management"&gt;Noisy error management&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#nil-interface-values"&gt;Nil interface values&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#struct-field-tags-runtime-dsl-in-a-string"&gt;Struct field tags: runtime DSL in a string&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#no-generics-at-least-not-for-you"&gt;No generics... at least not for you&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#go-has-few-data-structures-beyond-slice-and-map"&gt;Go has few data structures beyond slice and map&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#go-generate-ok-ish-but"&gt;go generate: ok-ish, but...&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/li&gt;
&lt;li&gt;&lt;a href="#conclusion"&gt;Conclusion&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="#a-few-days-later-3-on-hacker-news"&gt;A few days later: #3 on Hacker News!&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;
&lt;/div&gt;
&lt;h2 id="the-good"&gt;The Good&lt;/h2&gt;
&lt;h3 id="go-is-easy-to-learn"&gt;Go is easy to learn&lt;/h3&gt;
&lt;p&gt;That's a fact: if you know any kind of programming language, you can learn most of Go's syntax in a couple of hours with the "&lt;a href="https://tour.golang.org/welcome/1"&gt;Tour of Go&lt;/a&gt;", and write your first real program in a couple of days. Read and digest &lt;a href="https://golang.org/doc/effective_go.html"&gt;Effective Go&lt;/a&gt;, wander around in &lt;a href="https://golang.org/pkg/"&gt;the standard library&lt;/a&gt;, play with a web toolkit like &lt;a href="http://www.gorillatoolkit.org/"&gt;Gorilla&lt;/a&gt; or &lt;a href="https://gokit.io/"&gt;Go kit&lt;/a&gt; and you'll be a pretty decent Go developer.&lt;/p&gt;
&lt;p&gt;This is because Go's overarching goal is simplicity. When I started learning Go it reminded me when I first &lt;a href="https://en.wikipedia.org/wiki/Java_version_history#JDK_1.1"&gt;discovered Java&lt;/a&gt;: a simple language and a rich but not bloated standard library. Learning Go was a refreshing experience coming from today's Java heavy environment. Because of Go's simplicity, Go programs are very readable, even if error handling adds quite some noise (more on this below).&lt;/p&gt;
&lt;p&gt;But this may be false simplicity though. Quoting Rob Pike, &lt;a href="https://talks.golang.org/2015/simplicity-is-complicated.slide"&gt;simplicity is complicated&lt;/a&gt;, and we will see below that behind it there are a lot of gotchas waiting to bite us, and that simplicity and minimalism prevent writing DRY code.&lt;/p&gt;
&lt;h3 id="easy-concurrent-programming-with-goroutines-and-channels"&gt;Easy concurrent programming with goroutines and channels&lt;/h3&gt;
&lt;p&gt;Goroutines are probably the best feature of Go. They're lightweight computation threads, distinct from operating system threads.&lt;/p&gt;
&lt;p&gt;When a Go program executes what looks like a blocking I/O operation, the Go runtime actually suspends the goroutine and resumes it when an event indicates that some result is available. In the meantime other goroutines have been scheduled for execution. We therefore have the scalability benefits of asynchronous programming with a synchronous programming model.&lt;/p&gt;
&lt;p&gt;Goroutines are also lightweight: their stack &lt;a href="https://dave.cheney.net/2013/06/02/why-is-a-goroutines-stack-infinite"&gt;grows and shrinks on demand&lt;/a&gt;, which means having 100s or even 1000s of goroutines is not a problem.&lt;/p&gt;
&lt;p&gt;I once had a goroutine leak in an application: these goroutines were waiting for a channel to be closed before ending, and that channel was never closed (a common issue). The process was eating 90% of the CPU for no reason, and inspecting &lt;a href="https://golang.org/pkg/expvar/"&gt;expvars&lt;/a&gt; showed 600k idle goroutines! I guess the CPU was used by the goroutine scheduler.&lt;/p&gt;
&lt;p&gt;Sure, an actor system like Akka can &lt;a href="https://doc.akka.io/docs/akka/2.5/general/actor-systems.html#what-you-should-not-concern-yourself-with"&gt;handle millions of actors&lt;/a&gt; without a sweat, in part because actors don't have a stack, but they're far from being as easy to use as goroutines to write heavily concurrent request/response applications (i.e. http APIs).&lt;/p&gt;
&lt;p&gt;Channels are how goroutines should communicate: they provide a convenient programming model to send and receive data between goroutines without having to rely on fragile low level synchronization primitives. Channels come with their own set of &lt;a href="https://blog.golang.org/pipelines"&gt;usage&lt;/a&gt; &lt;a href="https://blog.golang.org/go-concurrency-patterns-timing-out-and"&gt;patterns&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Channels have to be thought out carefully though, as incorrectly sized channels (they're unbuffered by default) &lt;a href="https://www.danmrichards.com/blog/2018/03/26/goroutines-channels-and-waitgroups/"&gt;can lead to deadlocks&lt;/a&gt;. They also have a large number of &lt;a href="https://www.jtolio.com/2016/03/go-channels-are-bad-and-you-should-feel-bad/"&gt;gotchas and inconsistencies&lt;/a&gt;. We will also see below that using channels doesn't prevent race conditions because Go lacks immutability.&lt;/p&gt;
&lt;h3 id="great-standard-library"&gt;Great standard library&lt;/h3&gt;
&lt;p&gt;The Go &lt;a href="https://golang.org/pkg/"&gt;standard library&lt;/a&gt; is really great, particularly for everything related to network protocols or API development: http client and server, crypto, archive formats, compressions, sending email, etc. There's even an html parser and a rather powerful templating engine to produce text &amp;amp; html with automatic escaping to avoid XSS (used for example by &lt;a href="https://gohugo.io/templates/introduction/"&gt;Hugo&lt;/a&gt;).&lt;/p&gt;
&lt;p&gt;The various APIs are generally simple and easy to understand. They can sometimes look simplistic though: this is in part because the goroutine programming model means we just have to care about "seemingly synchronous" operations. This is also because a few versatile functions can also replace a lot of specialized ones as &lt;a href="../../../03/22/local-date-time-calculations-in-go/"&gt;I found out recently for time calculations&lt;/a&gt;.&lt;/p&gt;
&lt;h3 id="go-is-performant"&gt;Go is performant&lt;/h3&gt;
&lt;p&gt;Go compiles to a native executable. Many users of Go come from Python, Ruby or Node.js. For them, this is a mind-blowing experience as they see a huge increase in the number concurrent requests a server can handle. This is actually pretty normal when you come from interpreted languages with either no concurrency (Node.js) or a global interpreter lock. Combined to the language simplicity, this explains part of the excitement for Go.&lt;/p&gt;
&lt;p&gt;Compared to Java however, things are not so clear in &lt;a href="https://www.techempower.com/benchmarks/"&gt;raw performance benchmarks&lt;/a&gt;. Where Go beats Java though is on memory usage. Unless you're using &lt;a href="https://www.graalvm.org/docs/reference-manual/native-image/"&gt;Graal native-image&lt;/a&gt; which puts them in the same ballpark.&lt;/p&gt;
&lt;p&gt;Go's garbage collector is designed to &lt;a href="https://blog.golang.org/go15gc"&gt;prioritize latency&lt;/a&gt; and avoid stop-the-world pauses, which is particularly important in servers. This may come with a higher CPU cost, but in a horizontally scalable architecture this is easily solved by adding more machines. Remember that Go was designed at Google, who are all but short on resources!&lt;/p&gt;
&lt;p&gt;Compared to Java, the Go GC also has less work to do: a slice of structs is a contiguous array of structures, and not an array of pointers like in Java. Similarly Go maps use &lt;a href="https://golang.org/src/runtime/hashmap.go"&gt;small arrays as buckets&lt;/a&gt; for the same purpose. This means less work for the GC, and also better CPU cache locality.&lt;/p&gt;
&lt;p&gt;Go also beats Java for command-line utilities: being a native executable, a Go program has no startup cost contrarily to Java that first has to load and compile bytecode.&lt;/p&gt;
&lt;h3 id="language-defined-source-code-format"&gt;Language defined source code format&lt;/h3&gt;
&lt;p&gt;Some of the most heated debates in my career happened around the definition of a code format for the team. Go solves this by defining a canonical format for Go code. The &lt;a href="https://golang.org/cmd/gofmt/"&gt;&lt;code&gt;gofmt&lt;/code&gt;&lt;/a&gt; tool reformats your code and has no options.&lt;/p&gt;
&lt;p&gt;Like it or not, &lt;code&gt;gofmt&lt;/code&gt; defines how Go code should be formatted and that problem is therefore solved once for all!&lt;/p&gt;
&lt;h3 id="standardized-test-framework"&gt;Standardized test framework&lt;/h3&gt;
&lt;p&gt;Go comes with a great &lt;a href="https://golang.org/pkg/testing/"&gt;test framework&lt;/a&gt; in its standard library. It has support for parallel testing, benchmarks, and contains a lot of utilities to easily test network clients and servers.&lt;/p&gt;
&lt;h3 id="go-programs-are-great-for-operations"&gt;Go programs are great for operations&lt;/h3&gt;
&lt;p&gt;Compared to Python, Ruby or Node.js, having to install a single executable file is a dream for operations engineers. This is less and less an issue with the growing use of Docker, but standalone executables also means tiny Docker images.&lt;/p&gt;
&lt;p&gt;Go also has some built-in observability features with the &lt;a href="https://golang.org/pkg/expvar/"&gt;&lt;code&gt;expvar&lt;/code&gt;&lt;/a&gt; package to publish internal statuses and metrics, and makes it easy to add new ones. Be careful though, as they are &lt;a href="https://golang.org/pkg/expvar/#pkg-overview"&gt;automatically exposed&lt;/a&gt;, unprotected, on the default http request handler. Java has JMX for a similar purposes, but it's much more complex.&lt;/p&gt;
&lt;h3 id="defer-statement-to-avoid-forgetting-to-clean-up"&gt;Defer statement, to avoid forgetting to clean up&lt;/h3&gt;
&lt;p&gt;The &lt;code&gt;defer&lt;/code&gt; statement serves a purpose similar to &lt;code&gt;finally&lt;/code&gt; in Java: execute some clean up code at the end of the current function, no matter how this function is exited. The interesting thing with &lt;code&gt;defer&lt;/code&gt; is that it's not linked to a block of code, and can appear at any time. This allows the clean up code to be written as close as possible to the code that creates what needs to be cleaned up:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fileName&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="k"&gt;defer&lt;/span&gt; &lt;span class="nx"&gt;file&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="c1"&gt;// use file, we don&amp;#39;t have to think about closing it anymore&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Sure, Java's &lt;a href="https://docs.oracle.com/javase/tutorial/essential/exceptions/tryResourceClose.html"&gt;try-with-resource&lt;/a&gt; is less verbose and Rust &lt;a href="https://doc.rust-lang.org/rust-by-example/trait/drop.html"&gt;automatically claims resources&lt;/a&gt; when their owner is dropped, but since Go &lt;em&gt;requires&lt;/em&gt; you to be explicit about resource clean up, having it close to resource allocation is nice.&lt;/p&gt;
&lt;h3 id="new-types"&gt;New types&lt;/h3&gt;
&lt;p&gt;I love types, and something that irritates/scares me is when for example we pass around persisted object identifiers as &lt;code&gt;string&lt;/code&gt; or &lt;code&gt;long&lt;/code&gt; everywhere. We usually encode the id's type in the parameter name, but this is a cause of subtle bugs when a function has several identifiers as parameters and some call mismatches parameter order.&lt;/p&gt;
&lt;p&gt;Go has first-class support for new types, i.e. types that take an existing type and give it a separate identity, distinct from the original one. Contrarily to wrapping, new types have no runtime overhead. This allows the compiler to catch this kind of mistake:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="c1"&gt;// &amp;lt;-- new type&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ProductId&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;AddProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="nx"&gt;ProductId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;userId&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;UserId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;some-user-id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;productId&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;ProductId&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;some-product-id&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Right order: all fine&lt;/span&gt;
    &lt;span class="nx"&gt;AddProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c1"&gt;// Wrong order: would compile with raw strings&lt;/span&gt;
    &lt;span class="nx"&gt;AddProduct&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;productId&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;userId&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Compilation errors:&lt;/span&gt;
    &lt;span class="c1"&gt;// cannot use productId (type ProductId) as type UserId in argument to AddProduct&lt;/span&gt;
    &lt;span class="c1"&gt;// cannot use userId (type UserId) as type ProductId in argument to AddProduct&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Unfortunately the lack of generics makes the use of new types cumbersome as writing reusable code for them requires to cast values to/from the original type.&lt;/p&gt;
&lt;h2 id="the-bad"&gt;The Bad&lt;/h2&gt;
&lt;h3 id="go-ignored-advances-in-modern-language-design"&gt;Go ignored advances in modern language design&lt;/h3&gt;
&lt;p&gt;In &lt;a href="https://commandcenter.blogspot.fr/2012/06/less-is-exponentially-more.html"&gt;Less is exponentially more&lt;/a&gt;, Rob Pike explains that Go was meant to replace C and C++ at Google, and that its precursor was &lt;a href="https://swtch.com/~rsc/thread/newsqueak.pdf"&gt;Newsqueak&lt;/a&gt;, a language he wrote in the 80's. Go also has a lot of references to &lt;a href="https://en.wikipedia.org/wiki/Plan_9_from_Bell_Labs"&gt;Plan9&lt;/a&gt;, a distributed operating system the authors of Go developed in the 80's at Bell Labs.&lt;/p&gt;
&lt;p&gt;There's even a &lt;a href="https://golang.org/doc/asm"&gt;Go assembly&lt;/a&gt; directly inspired from Plan9. Why not using &lt;a href="https://llvm.org/"&gt;LLVM&lt;/a&gt; that would have provided a wide range of target architectures out of the box? I may also be missing something here, but why is that needed? If you need to write assembly to get the most out of the CPU, shouldn't you use directly the target CPU assembly language?&lt;/p&gt;
&lt;p&gt;Go creators deserve a lot of respect, but it looks like Go's design happened in a parallel universe (or their Plan9 lab?) where most of what happened in compilers and programming language design in the 90's and 2000's never happened. Or that Go was designed by system programmers who were also able to write a compiler.&lt;/p&gt;
&lt;p&gt;Functional programming? No mention of it. Generics? You don't need them, look at the mess they produced in C++! Even if slice, map and channels &lt;em&gt;are&lt;/em&gt; generic types as we'll see below.&lt;/p&gt;
&lt;p&gt;Go's goal was to replace C and C++, and it's apparent that its creators didn't look much elsewhere. They missed their target though, as C and C++ developers at Google didn't adopt it. My guess is that the primary reason is the garbage collector. Low level C developers fiercely reject managed memory as they have no control on what happens and when. They like this control, even if it comes with additional complexity and opens the door to memory leaks and buffer overflows. Interestingly, Rust has taken a completely different approach with automatic memory management without a GC.&lt;/p&gt;
&lt;p&gt;Go instead attracted users of scripting languages like Python and Ruby in the area of operation tools. They found in Go a way to have great performance and reduced memory/cpu/disk footprint. And more static typing too, which was new to them. The killer app for Go was Docker, that triggered its wide adoption in the devops world. The rise of Kubernetes strengthens this trend.&lt;/p&gt;
&lt;h3 id="interfaces-are-structural-types"&gt;Interfaces are structural types&lt;/h3&gt;
&lt;p&gt;Go interfaces are like Java interfaces or Scala &amp;amp; Rust traits: they define behaviour that is later implemented by a type (I won't call it "class" here).&lt;/p&gt;
&lt;p&gt;Unlike Java interfaces and Scala &amp;amp; Rust traits though, a type doesn't need to explicitly specify that it implements an interface: it just has to implement all functions defined in the interface. So Go interfaces are actually &lt;a href="https://en.wikipedia.org/wiki/Structural_type_system"&gt;structural typing&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;We may think that this is to allow interface implementations in other packages than the type they apply to, like class extensions that exist in Scala or Kotlin, or Rust traits, but this isn't the case: all methods related to a type must be defined in the type's package.&lt;/p&gt;
&lt;p&gt;Go isn't the only language to use structural typing, but I find it has several drawbacks:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;finding what types implement a given interface is hard as it relies on function definition matching. I often discover interesting implementations in Java or Scala by searching for classes that implement an interface. &lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;when adding a method to an interface, you will find what types need to be updated only when they are used as values of this interface type. This can go unnoticed for quite some time. Go recommends to have tiny interfaces with very few methods, which is a way to prevent this.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;a type may unknowingly implement an interface because it has the corresponding methods. But being accidental, the semantics of the implementation may be different from what is expected from the interface contract.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;&lt;em&gt;Update&lt;/em&gt;: for some ugliness with interfaces, see &lt;a href="#nil-interface-values"&gt;nil interface values&lt;/a&gt; below.&lt;/p&gt;
&lt;h3 id="interface-methods-dont-support-default-implementations"&gt;Interface methods don't support default implementations&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Added after the Go 1.13 release.&lt;/em&gt; That may not seem like a big deal, but read on.&lt;/p&gt;
&lt;p&gt;Go 1.13 introduced method chaining, adding a new &lt;code&gt;Unwrap&lt;/code&gt; method to errors. Since Go interfaces don't support default implementations for their methods, adding a method to an existing interface would break a lot of existing code. So &lt;a href="https://blog.golang.org/go1.13-errors#TOC_3.1."&gt;this new method is a "convention"&lt;/a&gt; rather than being part of the &lt;code&gt;error&lt;/code&gt; interface. And because of that we can't just call &lt;code&gt;err.Unwrap()&lt;/code&gt; to get the wrapped error. We have to use the separate function &lt;code&gt;errors.Unwrap(err)&lt;/code&gt; which uses &lt;a href="https://github.com/golang/go/blob/0377f061687771eddfe8de78d6c40e17d6b21a39/src/errors/wrap.go#L11-L22"&gt;dynamic typing tests&lt;/a&gt; to check if &lt;code&gt;Unwrap&lt;/code&gt; exists on its parameter.&lt;/p&gt;
&lt;p&gt;Bye-bye compile-time checks, hello cumbersome syntax for what could have been a simple method call! Java faced a similar issue in JDK8 with the introduction of lambdas, and added &lt;a href="https://docs.oracle.com/javase/tutorial/java/IandI/defaultmethods.html"&gt;default method implementation support&lt;/a&gt; to allow interfaces to evolve in a backwards-compatible way.&lt;/p&gt;
&lt;h3 id="no-enumerations"&gt;No enumerations&lt;/h3&gt;
&lt;p&gt;Go doesn't have enums, and in my opinion it's a missed opportunity.&lt;/p&gt;
&lt;p&gt;There is &lt;a href="https://github.com/golang/go/wiki/Iota"&gt;&lt;code&gt;iota&lt;/code&gt;&lt;/a&gt; to quickly generate auto-incrementing values, but it looks more like a hack than a feature. And a dangerous one, actually, since inserting a line in a series of iota-generated constants will change the value of the following ones. Since the generated value is the one that is used throughout the code, this can lead to interesting (not!) surprises.&lt;/p&gt;
&lt;p&gt;This also means there is no way in Go to have the compiler check that a &lt;code&gt;switch&lt;/code&gt; statement is exhaustive, and no way to describe the allowed values in a type.&lt;/p&gt;
&lt;h3 id="the-var-dilemma"&gt;The &lt;code&gt;:=&lt;/code&gt; / &lt;code&gt;var&lt;/code&gt; dilemma&lt;/h3&gt;
&lt;p&gt;Go provides two ways to declare a variable and assign it a value: &lt;code&gt;var x = "foo"&lt;/code&gt; and &lt;code&gt;x := "foo"&lt;/code&gt;. Why is that?&lt;/p&gt;
&lt;p&gt;The main differences are that &lt;code&gt;var&lt;/code&gt; allows declaration without initialization (and you then have to declare the type), like in &lt;code&gt;var x string&lt;/code&gt;, whereas &lt;code&gt;:=&lt;/code&gt; requires assignment and allows a mix of existing and new variables. My guess is that &lt;code&gt;:=&lt;/code&gt; was invented to make error handling &lt;em&gt;a bit&lt;/em&gt; less painful:&lt;/p&gt;
&lt;p&gt;With &lt;code&gt;var&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SomeFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err1&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;SomeOtherFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err2&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;With &lt;code&gt;:=&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;SomeFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;SomeOtherFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The &lt;code&gt;:=&lt;/code&gt; syntax also easily allows to accidentally shadow a variable. I was caught more than once by this, as &lt;code&gt;:=&lt;/code&gt; (declare and assign) is too close too &lt;code&gt;=&lt;/code&gt; (assign), as shown below:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;someCondition&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="nx"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;baz&amp;quot;&lt;/span&gt;
  &lt;span class="nx"&gt;doSomething&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="c1"&gt;// foo == &amp;quot;bar&amp;quot; even if &amp;quot;someCondition&amp;quot; is true&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3 id="zero-values-that-panic"&gt;Zero values that panic&lt;/h3&gt;
&lt;p&gt;Go doesn't have constructors. Because of that, it insists on the fact that the "&lt;a href="https://dave.cheney.net/2013/01/19/what-is-the-zero-value-and-why-is-it-useful"&gt;zero value&lt;/a&gt;" should be readily usable. This is an interesting approach, but in my opinion the simplification it brings is mostly for the language implementors.&lt;/p&gt;
&lt;p&gt;In practice, many types can't do useful things without proper initialization. Let's look a the &lt;code&gt;io.File&lt;/code&gt; object that is taken as an example in &lt;a href="https://golang.org/doc/effective_go.html#composite_literals"&gt;Effective Go&lt;/a&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;type File struct {
    *file // os specific
}

func (f *File) Name() string {
    return f.name
}

func (f *File) Read(b []byte) (n int, err error) {
    if err := f.checkValid(&amp;quot;read&amp;quot;); err != nil {
        return 0, err
    }
    n, e := f.read(b)
    return n, f.wrapErr(&amp;quot;read&amp;quot;, e)
}

func (f *File) checkValid(op string) error {
    if f == nil {
        return ErrInvalid
    }
    return nil
}
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;What can we see here?&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Calling &lt;code&gt;Name()&lt;/code&gt; on a zero-value &lt;code&gt;File&lt;/code&gt; will panic, because its &lt;code&gt;file&lt;/code&gt; field is nil.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;The &lt;code&gt;Read&lt;/code&gt; function, and &lt;a href="https://github.com/golang/go/blob/release-branch.go1.10/src/os/file.go"&gt;pretty much every other&lt;/a&gt; &lt;code&gt;File&lt;/code&gt; method, starts by checking if the file was initialized.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So basically a zero-value &lt;code&gt;File&lt;/code&gt; is not only useless, but can lead to panics. You &lt;em&gt;have&lt;/em&gt; to use one of the constructor functions like &lt;code&gt;Open&lt;/code&gt; or &lt;code&gt;Create&lt;/code&gt;. And checking proper initialization is an overhead you have to pay at every function call.&lt;/p&gt;
&lt;p&gt;There are countless types like this one in the standard library, and some that don't even try to do something useful with their zero value. Call any method on a zero-value &lt;code&gt;html.Template&lt;/code&gt;: they all panic.&lt;/p&gt;
&lt;p&gt;And there is also a serious gotcha with &lt;code&gt;map&lt;/code&gt;'s zero value: you can query it, but storing something in it will panic:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;m1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt; &lt;span class="c1"&gt;// empty map&lt;/span&gt;
&lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;m0&lt;/span&gt; &lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;     &lt;span class="c1"&gt;// zero map (nil)&lt;/span&gt;

&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;// outputs &amp;#39;0&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;   &lt;span class="c1"&gt;// outputs &amp;#39;0&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// outputs &amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt; &lt;span class="c1"&gt;// outputs &amp;#39;&amp;#39;&lt;/span&gt;
&lt;span class="nx"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;  &lt;span class="c1"&gt;// ok&lt;/span&gt;
&lt;span class="nx"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;bar&amp;quot;&lt;/span&gt;  &lt;span class="c1"&gt;// panics!&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This requires you to be careful when a structure has a &lt;code&gt;map&lt;/code&gt; field, since it has to be initialized before adding entries to it.&lt;/p&gt;
&lt;p&gt;So, as a developer, you have to constantly check if a structure you want to use requires to call a constructor function or if the zero value is useful. This is a lot of burden put on code writers for some simplifications in the language.&lt;/p&gt;
&lt;h3 id="go-doesnt-have-exceptions-oh-wait-it-does"&gt;Go doesn't have exceptions. Oh wait... it does!&lt;/h3&gt;
&lt;p&gt;The blog post "&lt;a href="https://dave.cheney.net/2012/01/18/why-go-gets-exceptions-right"&gt;Why Go gets exceptions right&lt;/a&gt;" explains in detail why exceptions are bad, and why the Go approach to require returning &lt;code&gt;error&lt;/code&gt; is better. I can agree with that, and exceptions are hard to deal with when using asynchronous programming or a functional style like Java streams (let's put aside that the former isn't necessary in Go thanks to goroutines and the latter is simply not possible). The blog post mentions &lt;code&gt;panic&lt;/code&gt; as "always fatal to your program, game over", which is fine.&lt;/p&gt;
&lt;p&gt;Now "&lt;a href="https://blog.golang.org/defer-panic-and-recover"&gt;Defer, panic and recover&lt;/a&gt;" that predates it, explains how to recover from panics (by actually catching them), and says "For a real-world example of panic and recover, see the json package from the Go standard library".&lt;/p&gt;
&lt;p&gt;And indeed, the json decoder has a &lt;a href="https://github.com/golang/go/blob/release-branch.go1.10/src/encoding/json/decode.go#L299"&gt;common error handling function&lt;/a&gt; that just panics, the panic being recovered in the top-level &lt;code&gt;unmarshal&lt;/code&gt; function that &lt;a href="https://github.com/golang/go/blob/release-branch.go1.10/src/encoding/json/decode.go#L173"&gt;checks the panic type&lt;/a&gt; and returns it as an error if it's a "local panic" or re-panics the error otherwise (losing the original panic's stacktrace on the way).&lt;/p&gt;
&lt;p&gt;To any Java developer this definitely looks like a &lt;code&gt;try&lt;/code&gt; / &lt;code&gt;catch (DecodingException ex)&lt;/code&gt;. So Go does have exceptions, uses them internally but tells you not to.&lt;/p&gt;
&lt;p&gt;Fun fact: a non-googler &lt;a href="https://github.com/golang/go/commit/74a92b8e8d0eae6bf9918ef16794b0363886713d"&gt;fixed the json decoder&lt;/a&gt; a couple of weeks ago to using regular errors bubbling up.&lt;/p&gt;
&lt;h2 id="the-ugly"&gt;The Ugly&lt;/h2&gt;
&lt;h3 id="the-dependency-management-nightmare"&gt;The dependency management nightmare&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Update: since this post was written, Go 1.11 has &lt;a href="https://golang.org/cmd/go/#hdr-Modules__module_versions__and_more"&gt;introduced module support&lt;/a&gt; with resolution based on semantic versioning. This solves most of the issues explained below, although the choice of the minimum version for dependency resolution is debatable (see also &lt;a href="http://aturon.github.io/2018/07/25/cargo-version-selection/"&gt;this post&lt;/a&gt; on why Rust's Cargo chooses the maximum version).&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Let's start by quoting Jaana Dogan (aka JBD), a well known gopher at Google, who recently vented her frustration on Twitter:&lt;/p&gt;
&lt;blockquote class="center-block twitter-tweet" data-lang="fr"&gt;&lt;p lang="en" dir="ltr"&gt;If dependency management is not resolved for another year, I am considering about quitting Go and never coming back. Dependency management issues routinely reverse all the joy I get from the language.&lt;/p&gt;&amp;mdash; JBD (@rakyll) &lt;a href="https://twitter.com/rakyll/status/976563654731579392?ref_src=twsrc%5Etfw"&gt;March 21, 2018&lt;/a&gt;&lt;/blockquote&gt;

&lt;script async src="https://platform.twitter.com/widgets.js" charset="utf-8"&gt;&lt;/script&gt;

&lt;p&gt;Let's put it simply: there is no dependency management in Go. All current solutions are just hacks and workarounds.&lt;/p&gt;
&lt;p&gt;This goes back its origins at Google, which famously uses a &lt;a href="https://research.google.com/pubs/pub45424.html"&gt;giant monolithic repository&lt;/a&gt; for all their source code. No need for module versioning, no need for 3rd party modules repositories, you build everything from your current branch. Unfortunately this doesn't work in the open Internet.&lt;/p&gt;
&lt;p&gt;Adding a dependency in Go means cloning that dependency's source code repo in your &lt;a href="https://golang.org/doc/code.html"&gt;&lt;code&gt;GOPATH&lt;/code&gt;&lt;/a&gt;. What version? The current master branch at the time of cloning, whatever it contains. What if different projects need different versions of a dependency? They can't. The notion of "version" doesn't even exist.&lt;/p&gt;
&lt;p&gt;Also, your own project has to live in &lt;code&gt;GOPATH&lt;/code&gt; or the compiler won't find it. Want to have your projects cleanly organized in a separate directory? You have to hack per-project &lt;code&gt;GOPATH&lt;/code&gt; or fiddle with symbolic links.&lt;/p&gt;
&lt;p&gt;The community has developed workarounds with a &lt;a href="https://github.com/golang/go/wiki/PackageManagementTools"&gt;large number of tools&lt;/a&gt;. Package management tools introduced vendoring and lock files holding the Git sha1 of whatever you cloned, to provide reproducible builds.&lt;/p&gt;
&lt;p&gt;Finally in Go 1.6 the &lt;code&gt;vendor&lt;/code&gt; directory was &lt;a href="https://golang.org/cmd/go/#hdr-Vendor_Directories"&gt;officially supported&lt;/a&gt;. But it's about vendoring what you cloned, and still not proper version management. No answer to conflicting imports from transitive dependencies that are usually solved with &lt;a href="https://semver.org/"&gt;semantic versioning&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Things are getting better though: &lt;code&gt;dep&lt;/code&gt;, the &lt;a href="https://golang.github.io/dep/"&gt;official dependency management tool&lt;/a&gt; was recently introduced to support vendoring. It supports versions (git tags) and has a version solver that follows semantic versioning conventions. It's not stable yet, but goes in the right direction. It still requires your project to live in &lt;code&gt;GOPATH&lt;/code&gt; though.&lt;/p&gt;
&lt;p&gt;But &lt;code&gt;dep&lt;/code&gt; may not live long though as &lt;a href="https://github.com/golang/vgo"&gt;&lt;code&gt;vgo&lt;/code&gt;&lt;/a&gt;, also from Google, wants to bring versioning in the language itself and has been making some waves lately.&lt;/p&gt;
&lt;p&gt;So dependency management in Go is nightmarish. It's painful to setup, and you don't think about it while developing until it blows up when you add a new import or simply want to pull a branch of one of your team members in your &lt;code&gt;GOPATH&lt;/code&gt;...&lt;/p&gt;
&lt;p&gt;Let's go back to the code now.&lt;/p&gt;
&lt;h3 id="mutability-is-hardcoded-in-the-language"&gt;Mutability is hardcoded in the language&lt;/h3&gt;
&lt;p&gt;There is no way to define immutable structures in Go: struct fields are mutable and the &lt;code&gt;const&lt;/code&gt; keyword doesn't apply to them. Go makes it easy however to copy an entire struct with a simple assignment, so we may think that passing arguments by value is all that is needed to have immutability at the cost of copying.&lt;/p&gt;
&lt;p&gt;However, and unsurprisingly, this does not copy values referenced by pointers. And the since built-in collections (map, slice and array) are references and are mutable, copying a struct that contains one of these just copies the pointer to the same underlying memory.&lt;/p&gt;
&lt;p&gt;The example below illustrates this:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;B&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;S&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x-A&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;x-B&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}}&lt;/span&gt;
    &lt;span class="nx"&gt;y&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt; &lt;span class="c1"&gt;// copy the struct&lt;/span&gt;
    &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;A&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;y-A&amp;quot;&lt;/span&gt;
    &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;B&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;y-B&amp;quot;&lt;/span&gt;

    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;y&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Outputs &amp;quot;{x-A [y-B]} {y-A [y-B]}&amp;quot; -- x was modified!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;So you have to be extremely careful about this, and not assume immutability if you pass a parameter by value.&lt;/p&gt;
&lt;p&gt;There are some &lt;a href="https://github.com/jinzhu/copier"&gt;deepcopy libraries&lt;/a&gt; that attempt to solve this using (slow) reflection, but they fall short since private fields can't be accessed with reflection. So defensive copying to avoid race conditions will be difficult, requiring lots of boilerplate code. Go doesn't even have a &lt;code&gt;Clone&lt;/code&gt; interface that would standardize this.&lt;/p&gt;
&lt;h3 id="slice-gotchas"&gt;Slice gotchas&lt;/h3&gt;
&lt;p&gt;Slices come with many gotchas: as explained in "&lt;a href="https://blog.golang.org/go-slices-usage-and-internals"&gt;Go slices: usage and internals&lt;/a&gt;", re-slicing a slice doesn't copy the underlying array for performance reasons. This is a laudable goal but means that sub-slices of a slice are just views that follow the mutations of the original slice. So don't forget to &lt;code&gt;copy()&lt;/code&gt; a slice if you want to separate it from its origin.&lt;/p&gt;
&lt;p&gt;Forgetting to &lt;code&gt;copy()&lt;/code&gt; becomes more dangerous with the &lt;code&gt;append&lt;/code&gt; function: appending values to a slice resizes the underlying array &lt;em&gt;if it doesn't have enough capacity&lt;/em&gt; to hold the new values. This means that the result of &lt;code&gt;append&lt;/code&gt; may or may not point to the original array depending on its initial capacity. This can cause hard to find non deterministic bugs.&lt;/p&gt;
&lt;p&gt;In the code below we see that the effects of a function appending values to a sub-slice vary depending on the capacity of the original slice:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;value=%v\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;value2&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;[:]&lt;/span&gt;
    &lt;span class="nx"&gt;value2&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;b&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;value=%v, value2=%v\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;z&amp;quot;&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;value=%v, value2=%v\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value2&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;slice1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="c1"&gt;// length 1, capacity 1&lt;/span&gt;

    &lt;span class="nx"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slice1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Output:&lt;/span&gt;
    &lt;span class="c1"&gt;// value=[a] -- ok&lt;/span&gt;
    &lt;span class="c1"&gt;// value=[a], value2=[a b] -- ok: value unchanged, value2 updated&lt;/span&gt;
    &lt;span class="c1"&gt;// value=[a], value2=[z b] -- ok: value unchanged, value2 updated&lt;/span&gt;

    &lt;span class="nx"&gt;slice10&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;make&lt;/span&gt;&lt;span class="p"&gt;([]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// length 1, capacity 10&lt;/span&gt;
    &lt;span class="nx"&gt;slice10&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;a&amp;quot;&lt;/span&gt;

    &lt;span class="nx"&gt;doStuff&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;slice10&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="c1"&gt;// Output:&lt;/span&gt;
    &lt;span class="c1"&gt;// value=[a] -- ok&lt;/span&gt;
    &lt;span class="c1"&gt;// value=[a], value2=[a b] -- ok: value unchanged, value2 updated&lt;/span&gt;
    &lt;span class="c1"&gt;// value=[z], value2=[z b] -- WTF?!? value changed???&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;h3 id="mutability-and-channels-race-conditions-made-easy"&gt;Mutability and channels: race conditions made easy&lt;/h3&gt;
&lt;p&gt;Go concurrency is &lt;a href="https://golang.org/doc/faq#csp"&gt;built on CSP using channels&lt;/a&gt; which makes coordinating goroutines much simpler and safer than synchronizing on shared data. The mantra here is "&lt;a href="https://blog.golang.org/share-memory-by-communicating"&gt;Do not communicate by sharing memory; instead, share memory by communicating&lt;/a&gt;". This is wishful thinking however and cannot be achieved safely in practice.&lt;/p&gt;
&lt;p&gt;As we saw above there is no way in Go to have immutable data structures. This means that once we send a pointer on a channel, it's game over: we share mutable data between concurrent processes. Of course a channel of structures (and not pointers) copies the values sent on the channel, but as we saw above, this doesn't deep-copy references, including slices and maps, which are intrinsically mutable. Same goes with struct fields of an interface type: they are pointers, and any mutation method defined by the interface is an open door to race conditions.&lt;/p&gt;
&lt;p&gt;So although channels apparently make concurrent programming easy, they don't prevent race conditions on shared data. And the intrinsic mutability of slices and maps makes them even more likely to happen.&lt;/p&gt;
&lt;p&gt;Talking about race conditions, Go includes a &lt;a href="https://blog.golang.org/race-detector"&gt;race condition detection mode&lt;/a&gt;, which instruments the code to find unsynchronized shared access. It can only detect race problems when they happen though, so mostly during integration or load tests, hoping those will exercise the race condition. It cannot realistically be enabled in production because of its high runtime cost, except for temporary debug sessions.&lt;/p&gt;
&lt;h3 id="noisy-error-management"&gt;Noisy error management&lt;/h3&gt;
&lt;p&gt;Something you will learn quickly in Go is the error handling pattern, repeated ad nauseam:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;someData&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;SomeFunction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Because Go claims to not support exceptions (&lt;a href="#go-doesnt-have-exceptions-oh-wait-it-does"&gt;although it does&lt;/a&gt;), every function that can end up with an error must have an &lt;code&gt;error&lt;/code&gt; as its last result. This applies in particular to every function that performs some I/O, so this verbose pattern is extremely prevalent in network applications, which is Go's primary area.&lt;/p&gt;
&lt;p&gt;Your eye will quickly develop a visual filter for this pattern and identify it as "yeah, error handling", but still it's a lot of noise and it's sometimes hard to find the actual code in the middle of error handling.&lt;/p&gt;
&lt;p&gt;First of all, your functions should really return the &lt;code&gt;error&lt;/code&gt; interface type and not a meaningful concrete type or the callers will encouter the dreaded &lt;em&gt;"Why is my nil error value not equal to nil?"&lt;/em&gt; issue that has a &lt;a href="https://golang.org/doc/faq#nil_error"&gt;dedicated FAQ entry&lt;/a&gt; (see also "nil interface values" below).&lt;/p&gt;
&lt;p&gt;There are also a few gotchas, since an error result can actually be a nominal case, as for example when reading from the ubiquitous &lt;code&gt;io.Reader&lt;/code&gt;: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;len&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;reader&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bytes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;EOF&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c1"&gt;// All good, end of file&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;In "&lt;a href="https://blog.golang.org/errors-are-values"&gt;Error has values&lt;/a&gt;" Rob Pike suggests some strategies to reduce error handling verbosity. I find them to be actually a dangerous band-aid:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;errWriter&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;w&lt;/span&gt;   &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;
    &lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ew&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;errWriter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="c1"&gt;// Write nothing if we already errored-out&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;doIt&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;fd&lt;/span&gt; &lt;span class="nx"&gt;io&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Writer&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;ew&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="nx"&gt;errWriter&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="nx"&gt;w&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;fd&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;b&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p1&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;c&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;d&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;p2&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;e&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt;&lt;span class="nx"&gt;f&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
    &lt;span class="c1"&gt;// and so on&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;ew&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Basically this recognizes that checking errors all the time is painful, and provides a pattern to just ignore errors in a write sequence until its end. So any operation performed to feed the writer once it has errored-out is executed even if we know it shouldn't. What if these are more expensive than just getting a slice? We've just wasted resources because Go's error handling is a pain. What if evaluating parameters has side effects? We've just introduced a serious bugs to simplify error handling...&lt;/p&gt;
&lt;p&gt;Rust had a similar issue: by not having exceptions (&lt;em&gt;really not&lt;/em&gt;, contrarily to Go), functions that can fail return &lt;code&gt;Result&amp;lt;T, Error&amp;gt;&lt;/code&gt; and require some pattern matching on the result. So Rust 1.0 came with the &lt;code&gt;try!&lt;/code&gt; macro and, recognizing the pervasiveness of this pattern, made it a &lt;a href="https://doc.rust-lang.org/rust-by-example/error/result/enter_question_mark.html"&gt;first-class language feature&lt;/a&gt;. So you have the terseness of the above code while keeping a correct error-handling.&lt;/p&gt;
&lt;p&gt;Transposing Rust's approach to Go is unfortunately not possible because Go doesn't have generics nor macros.&lt;/p&gt;
&lt;h3 id="nil-interface-values"&gt;Nil interface values&lt;/h3&gt;
&lt;p&gt;This is an update after &lt;a href="https://www.reddit.com/r/programming/comments/8bj4yc/go_the_good_the_bad_and_the_ugly/dx82cgz/"&gt;redditor jmickeyd&lt;/a&gt; shows a weird behaviour of &lt;code&gt;nil&lt;/code&gt; and interfaces, that definitely qualifies as ugly. I expanded it a bit:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Explodes&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Bang&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;Boom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Type Bomb implements Explodes&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Bomb&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Bomb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Bang&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;Bomb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Boom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;bomb&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Bomb&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt;
    &lt;span class="kd"&gt;var&lt;/span&gt; &lt;span class="nx"&gt;explodes&lt;/span&gt; &lt;span class="nx"&gt;Explodes&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;bomb&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;bomb&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;explodes&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;#39;0x0 (0x10a7060,0x0)&amp;#39;&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;explodes&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Not nil!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// &amp;#39;Not nil!&amp;#39; What are we doing here?!?!&lt;/span&gt;
        &lt;span class="nx"&gt;explodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bang&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;// works fine&lt;/span&gt;
        &lt;span class="nx"&gt;explodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Boom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;     &lt;span class="c1"&gt;// panic: value method main.Bomb.Boom called using nil *Bomb pointer&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nil!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;// why don&amp;#39;t we end up here?&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The above code verifies that &lt;code&gt;explodes&lt;/code&gt; is not &lt;code&gt;nil&lt;/code&gt; and yet the code panics in &lt;code&gt;Boom&lt;/code&gt; but not in &lt;code&gt;Bang&lt;/code&gt;. Why is that? The explanation is in the &lt;code&gt;println&lt;/code&gt; line: the &lt;code&gt;bomb&lt;/code&gt; pointer is &lt;code&gt;0x0&lt;/code&gt; which is effectively &lt;code&gt;nil&lt;/code&gt;, but &lt;code&gt;explodes&lt;/code&gt; is the non-nil &lt;code&gt;(0x10a7060,0x0)&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;This is because &lt;a href="https://research.swtch.com/interfaces"&gt;interface values are fat pointers&lt;/a&gt;. The first element of this pair is the pointer to the method dispatch table for the implementation of the &lt;code&gt;Bomb&lt;/code&gt; interface by the &lt;code&gt;Explodes&lt;/code&gt; type, and the second element is the address of the actual &lt;code&gt;Explodes&lt;/code&gt; object, which is &lt;code&gt;nil&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;The call to &lt;code&gt;Bang&lt;/code&gt; succeeds because it applies to &lt;em&gt;pointers&lt;/em&gt; to a &lt;code&gt;Bomb&lt;/code&gt;: there is no need to dereference the pointer to call the method. The &lt;code&gt;Boom&lt;/code&gt; method acts on a &lt;em&gt;value&lt;/em&gt; and so a call causes pointers to be dereferenced, which causes a panic.&lt;/p&gt;
&lt;p&gt;Note that if we had written &lt;code&gt;var explodes Explodes = nil&lt;/code&gt;, then &lt;code&gt;!= nil&lt;/code&gt; would have not succeeded.&lt;/p&gt;
&lt;p&gt;So how should we write the test in a safe way? We have to nil-check both the interface value and if non-nil, check the value pointed to by the interface object... using reflection!&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;explodes&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="kc"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="p"&gt;!&lt;/span&gt;&lt;span class="nx"&gt;reflect&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;ValueOf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;explodes&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;IsNil&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Not nil!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// we no more end up here&lt;/span&gt;
    &lt;span class="nx"&gt;explodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Bang&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="nx"&gt;explodes&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Boom&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nb"&gt;println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;nil!&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;     &lt;span class="c1"&gt;// &amp;#39;nil&amp;#39; -- all good!&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Bug or feature? The &lt;code&gt;Tour of Go&lt;/code&gt; has a &lt;a href="https://tour.golang.org/methods/12"&gt;dedicated page&lt;/a&gt; to explain this behaviour and clearly says &lt;em&gt;"Note that an interface value that holds a nil concrete value is itself non-nil"&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;Still, this is ugly and can cause very subtle bugs. It looks to me a like a big flaw in the language design to make its implementation easier.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Added in Dec '19:&lt;/em&gt; Other subtle bugs (or hard crashes, actually) can occur when a field of an interface type is updated concurrenly. Since assignment of a fat pointer isn't atomic, we may end up with a fat pointer pointing to a type and to a value of a different type. This breaks Go's memory safety and was demonstrated in &lt;a href="https://github.com/netanel01/ctf-writeups/blob/master/googlectf/2019/pwn_gomium/README.md"&gt;an exploit during a security challenge&lt;/a&gt;. This problem can probably be found with Go's race detector if your tests exercise it.&lt;/p&gt;
&lt;h3 id="struct-field-tags-runtime-dsl-in-a-string"&gt;Struct field tags: runtime DSL in a string&lt;/h3&gt;
&lt;p&gt;If you've used JSON in Go, you've certainly encountered something similar:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;User&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Id&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;    &lt;span class="s"&gt;`json:&amp;quot;id&amp;quot;`&lt;/span&gt;
    &lt;span class="nx"&gt;Email&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt; &lt;span class="s"&gt;`json:&amp;quot;email&amp;quot;`&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;  &lt;span class="s"&gt;`json:&amp;quot;name,omitempty&amp;quot;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;These are &lt;a href="https://golang.org/ref/spec#Struct_types"&gt;struct tags&lt;/a&gt; which the language spec says are a string "made visible through a reflection interface and take part in type identity for structs but are otherwise ignored". So basically, put whatever you want in this string, and parse it at runtime using reflection. And panic at runtime if the syntax isn't right.&lt;/p&gt;
&lt;p&gt;This string is actually field metadata, something that has existed for decades in many languages as "&lt;a href="https://en.wikipedia.org/wiki/Java_annotation"&gt;annotations&lt;/a&gt;" or "attributes". With language support, their syntax is formally defined and checked at compile time, while still being extensible.&lt;/p&gt;
&lt;p&gt;Why did Go decide to use a raw string that any library can decide to use with whatever DSL it wants, parsed at run time?&lt;/p&gt;
&lt;p&gt;Things can get awkward when you use multiple libraries: here's an example taken out of Protocol Buffer's &lt;a href="https://godoc.org/github.com/golang/protobuf/proto"&gt;Go documentation&lt;/a&gt;: &lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Test&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Label&lt;/span&gt;         &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;             &lt;span class="s"&gt;`protobuf:&amp;quot;bytes,1,req,name=label&amp;quot; json:&amp;quot;label,omitempty&amp;quot;`&lt;/span&gt;
    &lt;span class="nx"&gt;Type&lt;/span&gt;          &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="kt"&gt;int32&lt;/span&gt;              &lt;span class="s"&gt;`protobuf:&amp;quot;varint,2,opt,name=type,def=77&amp;quot; json:&amp;quot;type,omitempty&amp;quot;`&lt;/span&gt;
    &lt;span class="nx"&gt;Reps&lt;/span&gt;          &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;int64&lt;/span&gt;             &lt;span class="s"&gt;`protobuf:&amp;quot;varint,3,rep,name=reps&amp;quot; json:&amp;quot;reps,omitempty&amp;quot;`&lt;/span&gt;
    &lt;span class="nx"&gt;Optionalgroup&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="nx"&gt;Test_OptionalGroup&lt;/span&gt; &lt;span class="s"&gt;`protobuf:&amp;quot;group,4,opt,name=OptionalGroup&amp;quot; json:&amp;quot;optionalgroup,omitempty&amp;quot;`&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Side note: why are these tags so common when using JSON? Because in Go public fields must use &lt;code&gt;UpperCamelCase&lt;/code&gt;, or at least start with an uppercase letter, whereas the common convention for naming fields in JSON is either &lt;code&gt;lowerCamelCase&lt;/code&gt; or &lt;code&gt;snake_case&lt;/code&gt;. Hence the need for tedious tagging.&lt;/p&gt;
&lt;p&gt;The standard JSON encoder/decoder doesn't allow providing a naming strategy to automate the conversion, like &lt;a href="https://github.com/FasterXML/jackson-databind/blob/master/src/main/java/com/fasterxml/jackson/databind/PropertyNamingStrategy.java"&gt;Jackson does in Java&lt;/a&gt;. This probably explains why all fields in the Docker APIs are &lt;code&gt;UpperCamelCase&lt;/code&gt;: that avoided the need for its developers to write these unwieldy tags for their large API.&lt;/p&gt;
&lt;p&gt;Note however that the JSON parser is &lt;a href="https://godoc.org/encoding/json#Unmarshal"&gt;case insensitive&lt;/a&gt;, probably to make it easier to read &lt;code&gt;camelCase&lt;/code&gt; JSON that is so common without requiring annotations. But this also means that writing the same data structure back will use the default &lt;code&gt;UpperCamelCase&lt;/code&gt; naming and therefore produce a different JSON...&lt;/p&gt;
&lt;h3 id="no-generics-at-least-not-for-you"&gt;No generics... at least not for you&lt;/h3&gt;
&lt;p&gt;&lt;em&gt;Update (2020-06): the Go team has come up with a rather nice &lt;a href="https://go.googlesource.com/proposal/+/refs/heads/master/design/go2draft-type-parameters.md"&gt;proposal to add type parameters to Go&lt;/a&gt;, which will make this paragraph and the next one obsolete once it finally lands in the language. My only gripe is the builtin &lt;code&gt;comparable&lt;/code&gt; constraint that could be defined as regular interface that any type (and not only builtin ones) can implement, and similarly the lack of widely used concepts like &lt;code&gt;Ordered&lt;/code&gt; or &lt;code&gt;Hashable&lt;/code&gt;. But that may come in due time.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;It's hard to conceive a modern statically typed language without generics, but this is what you get with Go: it has no generics... or more precisely &lt;em&gt;almost&lt;/em&gt; no generics, which as we'll see makes it worse than no generics at all.&lt;/p&gt;
&lt;p&gt;The built-in slice, map, array and channel &lt;em&gt;are&lt;/em&gt; generic. Declaring a &lt;code&gt;map[string]MyStruct&lt;/code&gt; clearly shows the use of a generic type that has two parameters. Which is nice, as it allows type safe programming that catches all sorts of errors.&lt;/p&gt;
&lt;p&gt;There are however no user-definable generic data structures. This means that you cannot define reusable abstractions that may work with any type, in a type-safe way. You have to use untyped &lt;code&gt;interface{}&lt;/code&gt; and cast values to the proper type. Any mistake will only be caught at run time and will result in a panic. For a Java developer, it's like going back in the &lt;a href="https://en.wikipedia.org/wiki/Java_version_history#J2SE_5.0"&gt;pre-Java 5 times, in 2004&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;In "&lt;a href="https://commandcenter.blogspot.fr/2012/06/less-is-exponentially-more.html"&gt;Less is exponentially more&lt;/a&gt;", Rob Pike surprisingly puts generics and inheritance in the same "typed programming" bag and says he favors composition over inheritance. Not liking inheritance is fine (I actually write a lot of Scala with little inheritance) but generics answer another concern: reusability while preserving type safety. &lt;/p&gt;
&lt;p&gt;As we'll see below, the segregation between built-ins with generics and user-defined without generics has consequences on more than developer "comfort" and compile-time type safety: it impacts the whole Go ecosystem.&lt;/p&gt;
&lt;h3 id="go-has-few-data-structures-beyond-slice-and-map"&gt;Go has few data structures beyond slice and map&lt;/h3&gt;
&lt;p&gt;The Go ecosystem doesn't have many data structures that provide added or different functionality from the built-in slice and map. Recent versions of Go added the &lt;a href="https://golang.org/pkg/container/"&gt;containers&lt;/a&gt; package that provides a few of them. They all have the same caveat: they deal with &lt;code&gt;interface{}&lt;/code&gt; values, meaning you lose all type safety.&lt;/p&gt;
&lt;p&gt;Let's see an example with &lt;a href="https://medium.com/@deckarep/the-new-kid-in-town-gos-sync-map-de24a6bf7c2c"&gt;&lt;code&gt;sync.Map&lt;/code&gt;&lt;/a&gt; which is a concurrent map with lower thread contention than guarding a regular map with a mutex:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;MetricValue&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="kt"&gt;float64&lt;/span&gt;
    &lt;span class="nx"&gt;Time&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Time&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;metric&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;MetricValue&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="nx"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="mf"&gt;1.0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="nx"&gt;Time&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c1"&gt;// Store a value&lt;/span&gt;

    &lt;span class="nx"&gt;m0&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kd"&gt;map&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="nx"&gt;MetricValue&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="nx"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;

    &lt;span class="nx"&gt;m1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;sync&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Map&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="nx"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Store&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;metric&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// not type-checked&lt;/span&gt;

    &lt;span class="c1"&gt;// Load a value and print its square&lt;/span&gt;

    &lt;span class="nx"&gt;foo0&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;m0&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="c1"&gt;// rely on zero-value hack if not present&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Foo square = %f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="nx"&gt;foo1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Load&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="nx"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// have to make sure it&amp;#39;s present (not bad, actually)&lt;/span&gt;
        &lt;span class="nx"&gt;foo1&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;x&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;MetricValue&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt; &lt;span class="c1"&gt;// cast interface{} value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Foo square = %f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;math&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Pow&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;foo1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="c1"&gt;// Sum all elements&lt;/span&gt;

    &lt;span class="nx"&gt;sum0&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="nx"&gt;m0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// built-in range iteration on map&lt;/span&gt;
        &lt;span class="nx"&gt;sum0&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;v&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Sum = %f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sum0&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="nx"&gt;sum1&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="mf"&gt;0.0&lt;/span&gt;
    &lt;span class="nx"&gt;m1&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Range&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;key&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="kd"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="c1"&gt;// no &amp;#39;range&amp;#39; for you! Provide a function&lt;/span&gt;
        &lt;span class="nx"&gt;sum1&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;.(&lt;/span&gt;&lt;span class="nx"&gt;MetricValue&lt;/span&gt;&lt;span class="p"&gt;).&lt;/span&gt;&lt;span class="nx"&gt;Value&lt;/span&gt;        &lt;span class="c1"&gt;// with untyped interface{} parameters&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="kc"&gt;true&lt;/span&gt; &lt;span class="c1"&gt;// continue iteration&lt;/span&gt;
    &lt;span class="p"&gt;})&lt;/span&gt;
    &lt;span class="nx"&gt;fmt&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;&amp;quot;Sum = %f\n&amp;quot;&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;sum1&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is a great illustration of why there aren't many data structures in the Go ecosystem: they are a pain to use compared to the built-in slice and map. And for a simple reason: there are two categories of data structures in Go:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;aristocracy, the built-in slice, map, array and channel: type safe and generic, convenient to use with &lt;code&gt;range&lt;/code&gt;,&lt;/li&gt;
&lt;li&gt;rest of the world written in Go code: can't provide type safety, clumsy to use because of required casts.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So library-defined data structures really have to provide solid benefits for us developers to be willing to pay the price of loosing type safety and the additional code verbosity.&lt;/p&gt;
&lt;p&gt;The duality between built-in structures and Go code is painful in more subtle ways when we want to write reusable algorithms. This is an example from the standard library's &lt;a href="https://golang.org/pkg/sort/"&gt;&lt;code&gt;sort&lt;/code&gt; package&lt;/a&gt; to sort a slice:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kn"&gt;import&lt;/span&gt; &lt;span class="s"&gt;&amp;quot;sort&amp;quot;&lt;/span&gt;

&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;Person&lt;/span&gt; &lt;span class="kd"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;Name&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="nx"&gt;Age&lt;/span&gt;  &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// ByAge implements sort.Interface for []Person based on the Age field.&lt;/span&gt;
&lt;span class="kd"&gt;type&lt;/span&gt; &lt;span class="nx"&gt;ByAge&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;ByAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Len&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;           &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nb"&gt;len&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;ByAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Swap&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;      &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;=&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;],&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;a&lt;/span&gt; &lt;span class="nx"&gt;ByAge&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="nx"&gt;Less&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;j&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;i&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;&amp;lt;&lt;/span&gt; &lt;span class="nx"&gt;a&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;j&lt;/span&gt;&lt;span class="p"&gt;].&lt;/span&gt;&lt;span class="nx"&gt;Age&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;func&lt;/span&gt; &lt;span class="nx"&gt;SortPeople&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;people&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="nx"&gt;Person&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="nx"&gt;sort&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Sort&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ByAge&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;people&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Wait... Seriously? We have to define a new type &lt;code&gt;ByAge&lt;/code&gt; that has to implement 3 methods to bridge a generic (in the sense of "reusable") sort algorithm and the typed slice.&lt;/p&gt;
&lt;p&gt;The &lt;em&gt;only&lt;/em&gt; thing that should matter to us, developers, is the &lt;code&gt;Less&lt;/code&gt; function that compares two objects and is domain-dependent. Everything else is noise and boilerplate required by the simple fact that Go has no generics. And we have to repeat it for &lt;em&gt;each and every type that we want to sort&lt;/em&gt;. And every comparator too.&lt;/p&gt;
&lt;p&gt;&lt;em&gt;Update: &lt;a href="https://twitter.com/zekjur/status/983965201774071808"&gt;Michael Stapelberg&lt;/a&gt; points me to &lt;a href="https://golang.org/pkg/sort/#Slice"&gt;sort.Slice&lt;/a&gt; that I missed. Looks better, although it uses reflection under the hood (eek!) and requires the comparator function to be a closure on the slice to sort, which is still ugly.&lt;/em&gt;&lt;/p&gt;
&lt;p&gt;Every text explaining that Go doesn't need generics shows this as "the Go way" that allows having reusable algorithms while avoiding downcasting to &lt;code&gt;interface{}&lt;/code&gt;...&lt;/p&gt;
&lt;p&gt;Ok. Now to ease the pain, it would be nice if Go had macros that could generate this nonsensical boilerplate, right? Well, read on...&lt;/p&gt;
&lt;h3 id="go-generate-ok-ish-but"&gt;go generate: ok-ish, but...&lt;/h3&gt;
&lt;p&gt;Go 1.4 introduced the &lt;a href="https://blog.golang.org/generate"&gt;&lt;code&gt;go generate&lt;/code&gt; command&lt;/a&gt; to trigger code generation from annotations in the source code. Well, "annotation" here actually means a magic &lt;code&gt;//go:generate&lt;/code&gt; comment with strict rules: "the comment must start at the beginning of the line and have no spaces between the &lt;code&gt;//&lt;/code&gt; and the &lt;code&gt;go:generate&lt;/code&gt;". Get it wrong, add a space and no tool will warn you about it.&lt;/p&gt;
&lt;p&gt;This covers several kinds of use cases:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Generating Go code from other sources: ProtoBuf / Thrift / Swagger schemas, language grammars, etc.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Generating Go code that complements existing code, such as &lt;a href="https://godoc.org/golang.org/x/tools/cmd/stringer"&gt;stringer&lt;/a&gt; given as an example, that generates a &lt;code&gt;String()&lt;/code&gt; method for a series of typed constants.&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Add poor man's generics support. Since Go doesn't have generics, &lt;a href="https://github.com/cheekybits/genny"&gt;some clever band-aid solutions have emerged&lt;/a&gt; to generate them from template code.&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;First use case is ok, and the added value is that you don't have to fiddle with &lt;code&gt;Makefile&lt;/code&gt;s and that generation instructions can be close to the generated code's usage.&lt;/p&gt;
&lt;p&gt;For the second use case, many languages, such as Scala &amp;amp; Rust, have macros (which are mentioned in the &lt;a href="https://docs.google.com/document/d/1V03LUfjSADDooDMhe-_K59EgpTEm3V8uvQRuNMAEnjg/edit"&gt;design document&lt;/a&gt;) that have access to the source code's AST during compilation. Stringer actually &lt;a href="https://github.com/golang/tools/blob/master/cmd/stringer/stringer.go#L69"&gt;imports the Go compiler's parser&lt;/a&gt; to traverse the AST. Java doesn't have macros but annotation processors play the same role.&lt;/p&gt;
&lt;p&gt;Many languages also don't support macros so nothing fundamentally wrong here, except this fragile comment-driven syntax, which looks again like a quick hack that somehow does the job, and not something that was carefully thought out as coherent language design.&lt;/p&gt;
&lt;p&gt;Oh, and did you know that the Go compiler actually has a &lt;a href="https://dave.cheney.net/2018/01/08/gos-hidden-pragmas"&gt;number of annotations/pragmas&lt;/a&gt; and &lt;a href="https://dave.cheney.net/2013/10/12/how-to-use-conditional-compilation-with-the-go-build-tool"&gt;conditional compilation&lt;/a&gt; using this fragile comment syntax?&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;As you probably guessed, I have a love/hate relation with Go. Go is a bit like this friend that you like to hang out with because he's fun and great for small talk around beers, but that you find boring or painful when you want to have deeper conversations, and that you don't want to go on vacation with.&lt;/p&gt;
&lt;p&gt;I like Go to quickly develop simple APIs (although JSON support is pretty basic compared to Java's &lt;a href="https://github.com/FasterXML/jackson"&gt;Jackson&lt;/a&gt; or Rust's &lt;a href="https://serde.rs/"&gt;serde&lt;/a&gt;) or network stuff that goroutines make easy to reason about, I hate its limited expressiveness and half-baked type system when I have to implement business logic, and I hate all its quirks and gotchas waiting to hit you hard. Go requires a lot of attention and discipline to avoid them.&lt;/p&gt;
&lt;p&gt;Up to recently there wasn't really an alternative in the space that Go occupies, which is developing efficient native executables without incurring the pain of C or C++. &lt;a href="https://www.rust-lang.org/"&gt;Rust&lt;/a&gt; is progressing quickly, and the more I play with it, the more I find it extremely interesting and superbly designed. I have the feeling that Rust is one of those friends that take some time to get along with, but that you'll finally want to engage with for a long term relationship.&lt;/p&gt;
&lt;p&gt;Going back on more technical aspects, you'll find articles saying that Rust and Go don't play in the same park, that Rust is a systems language because it doesn't have a GC, etc. I think this is becoming less and less true. Rust is climbing higher in the stack with great &lt;a href="http://www.arewewebyet.org/"&gt;web frameworks&lt;/a&gt; and nice &lt;a href="http://diesel.rs/"&gt;ORM&lt;/a&gt;s. It also gives you that warm feeling of "if it compiles, errors will come from the logic I wrote, not language quirks I forgot to pay attention to".&lt;/p&gt;
&lt;p&gt;We also see some interesting movements in the container/service mesh area with Buoyant (developers of &lt;a href="https://linkerd.io/"&gt;Linkerd&lt;/a&gt;) developing their new Kubernetes service mesh &lt;a href="https://buoyant.io/2017/12/05/introducing-conduit/"&gt;Conduit&lt;/a&gt; as a combination of Go for the control plane (I guess because of the available &lt;a href="https://github.com/runconduit/conduit/blob/master/Gopkg.toml"&gt;Kubernetes libraries&lt;/a&gt;) and Rust for the data plane for its efficiency and robustness, and also &lt;a href="https://www.sozu.io/"&gt;Sozu proxy&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;&lt;a href="https://swift.org/"&gt;Swift&lt;/a&gt; is also part of this family or recent alternatives to C and C++. Its ecosystem is still too Apple-centric though, even if it's now available on Linux and has emerging &lt;a href="https://swift.org/server-apis/"&gt;server-side APIs&lt;/a&gt; and the &lt;a href="https://github.com/apple/swift-nio"&gt;Netty framework&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;There is of course no silver bullet and no one-size-fits-all. But knowing the gotchas of the tools you use is important. I hope this blog post has taught you some things about Go that you weren't aware of, so that you avoid the traps rather than getting caught!&lt;/p&gt;
&lt;h2 id="a-few-days-later-3-on-hacker-news"&gt;A few days later: #3 on Hacker News!&lt;/h2&gt;
&lt;p&gt;&lt;em&gt;Update, 3 days after publishing&lt;/em&gt;: The reaction to this article has been amazing. It has made the front page of &lt;a href="https://news.ycombinator.com/item?id=16830153"&gt;Hacker News&lt;/a&gt; (best rank I saw was #3) and &lt;a href="https://www.reddit.com/r/programming/comments/8bj4yc/go_the_good_the_bad_and_the_ugly/"&gt;/r/programming&lt;/a&gt; (best rank I saw was #5), and got &lt;a href="https://twitter.com/search?l=&amp;amp;q=https%3A%2F%2Fbluxte.net%2Fmusings%2F2018%2F04%2F10%2Fgo-good-bad-ugly%2F"&gt;some traction on Twitter&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The comments are generally positive (even on &lt;a href="https://www.reddit.com/r/golang/comments/8bj4tx/go_the_good_the_bad_and_the_ugly/"&gt;/r/golang/&lt;/a&gt;) or at least recognize that the article is balanced and tries to be fair. People on &lt;a href="https://www.reddit.com/r/rust/comments/8bjio2/xpost_from_rprogramming_go_the_good_the_bad_and/"&gt;/r/rust&lt;/a&gt; of course liked my interest in Rust. Someone I never heard of even emailed me saying &lt;em&gt;"I just wanted to let you know that I thought your write-up was the best ever.  Thanks for all the work you put into it"&lt;/em&gt;.&lt;/p&gt;
&lt;p&gt;That was the hard part when writing it: try to be as factual and impartial as possible. This is of course not entirely possible as everyone has their own preferences, and why I focused on unexpected surprises and language ergonomics: how much the language helps you rather than getting in the way, or at least &lt;em&gt;my&lt;/em&gt; way.&lt;/p&gt;
&lt;p&gt;I also searched for code samples in the standard library or on &lt;a href="https://golang.org/"&gt;golang.org&lt;/a&gt; and quoted people from the Go team, to base my analysis on authoritative material and avoid &lt;em&gt;"meh, you quoted someone who got it wrong"&lt;/em&gt; reactions.&lt;/p&gt;
&lt;p&gt;Writing this article used most of my evenings for two weeks, but it was lots of fun. And this is what you get when you do serious and honest work: lots of good vibes from teh Internets (if you ignore the few trolls and always grumpy people). Very motivating to write more in depth content!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Mon, 22 Jun 2020 15:10:11 +0200</pubDate><guid isPermaLink="false">tag:bluxte.net,2018-04-10:musings/2018/04/10/go-good-bad-ugly/</guid></item><item><title>Local date time calculations in Go</title><link>http://bluxte.net/musings/2018/03/22/local-date-time-calculations-in-go/</link><description>&lt;p&gt;For a side project I'm writing in Go, I needed to send an email to each registered user during the night. Their night actually, according to each user's time zone. More precisely at a random time between 3am and 4am to spread email sending and avoid any rate limiting from SMTP providers or spam detection systems.&lt;/p&gt;
&lt;p&gt;Coming from a Java/Scala background, I was looking for a large number of setters or offsetting methods on the time type. Here's what it would look like in Scala using classes in &lt;code&gt;java.time&lt;/code&gt;:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;tz&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;user&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;timeZone&lt;/span&gt; &lt;span class="c1"&gt;// e.g. &amp;quot;Europe/Paris&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;// the current wall clock time in the user&amp;#39;s time zone&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;userTime&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="nc"&gt;ZonedDateTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="nc"&gt;ZoneId&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;of&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tz&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// tomorrow sometime between 3am and 4am&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;emailSendTime&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;userTime&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plusDays&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;withHour&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    &lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;plusSeconds&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;nextInt&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="o"&gt;))&lt;/span&gt;

&lt;span class="c1"&gt;// the instant (absolute timestamp) to be used by the task scheduler&lt;/span&gt;
&lt;span class="k"&gt;val&lt;/span&gt; &lt;span class="n"&gt;emailInstant&lt;/span&gt; &lt;span class="k"&gt;=&lt;/span&gt; &lt;span class="n"&gt;emailLocalTime&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;toInstant&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Go puts simplicity first (too much IMHO but that's another discussion) and has only one type for time: &lt;a href="https://golang.org/pkg/time/#Time"&gt;&lt;code&gt;time.Time&lt;/code&gt;&lt;/a&gt;. No wall clock time like Java's &lt;code&gt;LocalDateTime&lt;/code&gt; or &lt;code&gt;ZonedDateTime&lt;/code&gt; and no absolute &lt;code&gt;Instant&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;Similarly, &lt;code&gt;time.Time&lt;/code&gt; has no setter method and only one offsetting method, &lt;code&gt;AddDate(years, months, days)&lt;/code&gt;. So with these in hand, how do we implement the above calculation?&lt;/p&gt;
&lt;p&gt;Go has a couple of tricks here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;&lt;code&gt;time.Time&lt;/code&gt; always has an associated time zone that by default is UTC.&lt;/li&gt;
&lt;li&gt;&lt;code&gt;time.Time&lt;/code&gt; has two destructuring functions, &lt;code&gt;Time.Date()&lt;/code&gt; and &lt;code&gt;Time.Clock&lt;/code&gt; that return the date and clock's constituents.&lt;/li&gt;
&lt;li&gt;there is a &lt;a href="https://golang.org/pkg/time/#Date"&gt;&lt;code&gt;Date(year, month, day, hour, min, sec, nsec, location)&lt;/code&gt;&lt;/a&gt; constructor function.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;With that in hand, we can write the Go version:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;LoadLocation&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;user&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;TimeZone&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c1"&gt;// e.g. &amp;quot;Europe/Paris&amp;quot;&lt;/span&gt;

&lt;span class="c1"&gt;// the current wall clock time in the user&amp;#39;s time zone&lt;/span&gt;
&lt;span class="nx"&gt;userTime&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;().&lt;/span&gt;&lt;span class="nx"&gt;In&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;location&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c1"&gt;// destructure the time&amp;#39;s date&lt;/span&gt;
&lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;userTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

&lt;span class="nx"&gt;emailSendTime&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nx"&gt;time&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Date&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="nx"&gt;year&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;month&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;day&lt;/span&gt;&lt;span class="o"&gt;+&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;        &lt;span class="c1"&gt;// date&lt;/span&gt;
    &lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Intn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3600&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;  &lt;span class="c1"&gt;// time (with nanosec)&lt;/span&gt;
    &lt;span class="nx"&gt;userTime&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Location&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;(yes, I skipped the dreaded &lt;code&gt;if err != nil&lt;/code&gt; after &lt;code&gt;LoadLocation&lt;/code&gt;)&lt;/p&gt;
&lt;p&gt;An interesting thing to note regarding the &lt;code&gt;Date&lt;/code&gt; function, is that we can pass out of range values for all parameters. For example, passing &lt;code&gt;18&lt;/code&gt; for the month will set it to &lt;code&gt;6&lt;/code&gt; and increment the year by one.&lt;/p&gt;
&lt;p&gt;Nothing complicated here, but I had to "unlearn" what I knew from Java to find that a couple of simple functions were all that was needed to perform arbitrary time calculations. Now I need to look at how this works in Rust :-)&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Thu, 22 Mar 2018 22:14:21 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2018-03-22:musings/2018/03/22/local-date-time-calculations-in-go/</guid></item><item><title>Micro benchmarks can make you short-sighted</title><link>http://bluxte.net/musings/2016/11/26/micro-benchmarks-can-make-you-short-sighted/</link><description>&lt;p&gt;In the last 24 hours, two articles related to code benchmarking showed up on my &lt;a href="https://twitter.com/bluxte"&gt;Twitter timeline&lt;/a&gt;, where the authors describe the optimization of a tiny bit of code via successive benchmarks. Both articles immediately triggered the same reaction in my head: "WTF, this is wrong! Why did they wrote this in the first place, and why do they focus on optimizing this bad solution?"&lt;/p&gt;
&lt;p&gt;The second article even ends up with a solution that not only does not solve the original problem, but is really suboptimal. So in true &lt;a href="https://xkcd.com/386/"&gt;xkcd#386&lt;/a&gt; fashion I had to do something about it!&lt;/p&gt;
&lt;p&gt;Both articles show that benchmark-driven optimization can lead people to focus on incrementally improving what is there rather than taking a step back and thinking about the original problem in a different way.&lt;/p&gt;
&lt;h2 id="sum-of-fizz-and-buzz"&gt;Sum of fizz and buzz&lt;/h2&gt;
&lt;p&gt;The first article, "&lt;a href="https://medium.freecodecamp.com/what-i-learned-from-writing-six-functions-that-all-did-the-same-thing-b38fd48f0d55"&gt;What I learned from writing six functions that all did the same thing&lt;/a&gt;", describes a variant of &lt;a href="https://en.wikipedia.org/wiki/Fizz_buzz#Programming_interviews"&gt;Fizz buzz&lt;/a&gt;: given a number &lt;em&gt;n&lt;/em&gt;, return the sum of all multiples of 3 &amp;amp; 5 that are between 0 and &lt;em&gt;n&lt;/em&gt;. The initial solution is to build an array of multiples of 3 or 5, and then sum the members of this array. WTF? Two loops and an array? How can one even come up with this solution in the first place?&lt;/p&gt;
&lt;p&gt;Reading the code, it seems trivial that the array not only useless but harmful by requiring memory allocation and two loops! After many incremental improvements to the sum of the array elements, the author finally takes a step back and replaces it by a single loop where the sum computed on the fly.&lt;/p&gt;
&lt;p&gt;And he feels like a champion since it's 28 times faster... until &lt;a href="https://medium.freecodecamp.com/what-i-learned-from-writing-six-functions-that-all-did-the-same-thing-b38fd48f0d55#7f31"&gt;someone comes up&lt;/a&gt; with the fact that it can be solved by adding/subtracting the &lt;a href="https://en.wikipedia.org/wiki/Arithmetic_progression#Sum"&gt;sum of arithmetic progressions&lt;/a&gt; with common difference of 3, 5 &amp;amp; 15 (some math we learn in high school in France).&lt;/p&gt;
&lt;p&gt;This article ends on a positive note though: even if there were 3 versions focusing on an incremental approach of the bad part of the solution (the array), the author finally takes a step back to consider things from a different angle, and ends up with a decent solution even if we could further reduce the number of useless iterations in the loop.&lt;/p&gt;
&lt;h2 id="a-loop-that-should-have-been-a-lookup-table"&gt;A loop that should have been a lookup table&lt;/h2&gt;
&lt;p&gt;The second article, "&lt;a href="http://blog.couchbase.com/all-the-small-things---jvm-profiling-lessons-from-the-trenches"&gt;All The Small Things - JVM Profiling Lessons From The Trenches&lt;/a&gt;" starts by analyzing memory allocation in the CouchBase client library, wondering why there are so many allocations of an array of enums. The finding is that in Java, &lt;code&gt;SomeEnumType.values()&lt;/code&gt; allocates an array at
each call.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Allocating an array for a list of constants?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Let's study this first: the list of values for an enum is constant, so why do we need to allocate a brand new array at each call to &lt;code&gt;values()&lt;/code&gt;? Simply because arrays in Java are mutable, and that the caller can thus modify the contents of the resulting array. Returning a singleton array would potentially cause weird bugs in subsequent callers of this method if someone modifies it.&lt;/p&gt;
&lt;p&gt;It certainly almost never happens in real code, but the JDK had to make sure it is protected against it. A solution would have been for the method to return an unmodifiable &lt;code&gt;List&lt;/code&gt; rather than a low-level mutable array.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Linear scan? Srsly?&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Back to the article: they have an &lt;a href="https://github.com/couchbase/couchbase-jvm-core/blob/master/src/main/java/com/couchbase/client/core/endpoint/kv/KeyValueStatus.java"&gt;enum representing status codes&lt;/a&gt; and want to, given a numerical status code, find the corresponding enum value. The initial solution for this was to loop over all enum values until we find the one that has the correct code.&lt;/p&gt;
&lt;p&gt;This is when the "WTF?!" kicks in: this code searches for a single element in a collection, given the value of a property of that element. Hmm... wait... doesn't it sound like a table lookup? It sure does! And the implementation is a very inefficient linear scan! Fortunately, looking at the enum definition, it looks like the most frequent statuses come first, alleviating a bit the cost of the scan. But still.&lt;/p&gt;
&lt;p&gt;Then the article goes to great length about progressive improvements by adding fast path checks for common codes. This is indeed a good idea, but the codes in the fast path are mostly at the beginning of the list, so the performance gain shouldn't be high compared to a linear scan.&lt;/p&gt;
&lt;p&gt;But more importantly, it does not solve the original problem, which was reducing memory allocation: for values out of the fast path, &lt;code&gt;values()&lt;/code&gt; is still called, with the associated array allocation/copy.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Solving the original problem, even if badly&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So before going to constant time lookup, let's remove array allocation, and keep a loop with no fast path. This is still a bad linear scan, but allows us some interesting comparison with the fast path solution (see the &lt;a href="https://github.com/swallez/jmh-couchbase-keyvaluestatus"&gt;full code on GitHub&lt;/a&gt;):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// Original implementation, with no fast path&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;valueOfLoop&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// Current code: fast path, but array allocation for other values&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;SUCCESS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;SUCCESS&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ERR_NOT_FOUND&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ERR_NOT_FOUND&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ERR_EXISTS&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ERR_EXISTS&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;ERR_NOT_MY_VBUCKET&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;ERR_NOT_MY_VBUCKET&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="n"&gt;keyValueStatus&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyValueStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;keyValueStatus&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="c1"&gt;// No fast path, use a static array to avoid allocation when calling values()&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;VALUES&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;();&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;valueOfLoopOnConstantArray&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;VALUES&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Benchmark code:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nd"&gt;@Param&lt;/span&gt;&lt;span class="o"&gt;({&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;0&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0x00, Success&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;1&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0x01, Not Found&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;134&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// 0x86 Temporary Failure&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;255&amp;quot;&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
        &lt;span class="s"&gt;&amp;quot;1024&amp;quot;&lt;/span&gt; &lt;span class="c1"&gt;// undefined&lt;/span&gt;
&lt;span class="o"&gt;})&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;

&lt;span class="nd"&gt;@Benchmark&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;loopNoFastPath&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOfLoop&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Benchmark&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;loopFastPath&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOf&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="nd"&gt;@Benchmark&lt;/span&gt;
&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;loopOnConstantArray&lt;/span&gt;&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;valueOfLoopOnConstantArray&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Benchmark results (benchmark name truncated to fit the page width):&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Benchmark               (code)  Mode  Samples   Score  Score error  Units

loopNoFastPath               0  avgt       10  19.383        0.331  ns/op
loopNoFastPath               1  avgt       10  19.243        0.376  ns/op
loopNoFastPath             134  avgt       10  24.855        0.651  ns/op
loopNoFastPath             255  avgt       10  30.587        0.833  ns/op
loopNoFastPath            1024  avgt       10  30.619        1.209  ns/op

loopFastPath                 0  avgt       10   3.044        0.092  ns/op
loopFastPath                 1  avgt       10   3.040        0.051  ns/op
loopFastPath               134  avgt       10  25.070        0.637  ns/op
loopFastPath               255  avgt       10  31.215        1.089  ns/op
loopFastPath              1024  avgt       10  32.464        0.930  ns/op

loopOnConstantArray          0  avgt       10   2.975        0.086  ns/op
loopOnConstantArray          1  avgt       10   3.035        0.080  ns/op
loopOnConstantArray        134  avgt       10  10.215        0.269  ns/op
loopOnConstantArray        255  avgt       10  16.856        0.679  ns/op
loopOnConstantArray       1024  avgt       10  17.015        0.577  ns/op
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We get some pretty interesting results here:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;when looping on a constant array, avoiding memory allocation, the worst case scenario (255 &amp;amp; 1024, out of the value range) are still better than the best case scenario (0) with memory allocation.&lt;/li&gt;
&lt;li&gt;for the values at the beginning of the list, iterating on a couple of values on the constant array isn't different that testing the fast path. It's easy to understand: the fast path is a partial loop unrolling.&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;So to solve the original memory allocation issue, rather than adding a fast path we could have just added a static copy of &lt;code&gt;values()&lt;/code&gt; and be done with it!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Constant time lookup&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;But this approach is still bad, with a linear scan. Let's do a constant time lookup. For this, the classical Java approach is to use a &lt;code&gt;HashMap&lt;/code&gt;, which we'll initialize once in a &lt;code&gt;static&lt;/code&gt; block:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&lt;/span&gt;&lt;span class="n"&gt;Short&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;&amp;gt;&lt;/span&gt; &lt;span class="n"&gt;code2statusMap&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;HashMap&lt;/span&gt;&lt;span class="o"&gt;&amp;lt;&amp;gt;();&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;code2statusMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;put&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;valueOfLookupMap&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;code2statusMap&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;getOrDefault&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;And here's the benchmark:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Benchmark               (code)  Mode  Samples   Score  Score error  Units
lookupMap                    0  avgt       10   4.954        0.134  ns/op
lookupMap                    1  avgt       10   4.036        0.125  ns/op
lookupMap                  134  avgt       10   5.597        0.157  ns/op
lookupMap                  255  avgt       10   4.006        0.144  ns/op
lookupMap                 1024  avgt       10   6.752        0.228  ns/op
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This is goes from 1/3 slower for the first values to more than 4 times faster for the last values. Time is no more increasing linearly, but we are slower on the most frequent values.&lt;/p&gt;
&lt;p&gt;There is also a large variance, from 4.0 to 6.7 ns. Where does this come from? It's caused by hash collisions in the internal &lt;code&gt;HashMap&lt;/code&gt; lookup table, causing lookups to &lt;a href="https://en.wikipedia.org/wiki/Hash_table#Collision_resolution"&gt;degenerate into linear scan&lt;/a&gt; on the colliding key values.&lt;/p&gt;
&lt;p&gt;So this looks like an acceptable solution, giving a more or less constant time lookup without large object allocation.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Don't forget boxing&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;There is still some allocation happening though: a Java &lt;code&gt;HashMap&lt;/code&gt; expects objects for its keys, not primitive types. So we have an implicit boxing of &lt;code&gt;code&lt;/code&gt; when looking up in the map. The JDK has an &lt;a href="http://hg.openjdk.java.net/jdk8/jdk8/jdk/file/687fd7c7986d/src/share/classes/java/lang/Short.java#l203"&gt;internal cache for small values&lt;/a&gt; to alleviate part of this problem. But for codes over 127 it still allocates a &lt;code&gt;Short&lt;/code&gt; object.&lt;/p&gt;
&lt;p&gt;The code of this allocation doesn't show up in the benchmarks results though, with 255 (not cached) being similar to 0 &amp;amp; 1 (cached). There's probably some HotSpot optimisation happening behind the scenes, furthermore considering that &lt;code&gt;Short.valueOf()&lt;/code&gt; is an &lt;a href="http://hg.openjdk.java.net/jdk8/jdk8/hotspot/file/87ee5ee27509/src/share/vm/classfile/vmSymbols.hpp#l1059"&gt;intrinsic function&lt;/a&gt;, i.e. calls to this method are &lt;a href="http://www.slideshare.net/RednaxelaFX/green-teajug-hotspotintrinsics02232013"&gt;hijacked by the JVM and implemented in native code&lt;/a&gt; (without going through JNI).&lt;/p&gt;
&lt;p&gt;To completely remove this boxing, we could consider the excellent &lt;a href="https://github.com/carrotsearch/hppc"&gt;CarrotSearch's high performance primitive collections&lt;/a&gt;. But there's an even simpler solution.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;A good old reverse lookup table&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;This is what immediately came to my mind when looking at &lt;code&gt;KeyValueStatus&lt;/code&gt; &lt;a href="https://github.com/couchbase/couchbase-jvm-core/blob/master/src/main/java/com/couchbase/client/core/endpoint/kv/KeyValueStatus.java"&gt;source code&lt;/a&gt;. The code values range from 0 to 0xCC (204), which is small enough to allow keeping a simple lookup table in an array:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="c1"&gt;// Lookup table: code -&amp;gt; KeyValueStatus&lt;/span&gt;
&lt;span class="kd"&gt;private&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;[]&lt;/span&gt; &lt;span class="n"&gt;code2status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="k"&gt;new&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="mh"&gt;0x100&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;

&lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Arrays&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;fill&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code2status&lt;/span&gt;&lt;span class="o"&gt;,&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="n"&gt;keyValueStatus&lt;/span&gt; &lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;values&lt;/span&gt;&lt;span class="o"&gt;())&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;keyValueStatus&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;code2status&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;keyValueStatus&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;code&lt;/span&gt;&lt;span class="o"&gt;()]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;keyValueStatus&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
        &lt;span class="o"&gt;}&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;

&lt;span class="kd"&gt;public&lt;/span&gt; &lt;span class="kd"&gt;static&lt;/span&gt; &lt;span class="n"&gt;KeyValueStatus&lt;/span&gt; &lt;span class="nf"&gt;valueOfLookupArray&lt;/span&gt;&lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="kd"&gt;final&lt;/span&gt; &lt;span class="kt"&gt;short&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;(&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="n"&gt;code2status&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="na"&gt;length&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;code2status&lt;/span&gt;&lt;span class="o"&gt;[&lt;/span&gt;&lt;span class="n"&gt;code&lt;/span&gt;&lt;span class="o"&gt;];&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt; &lt;span class="k"&gt;else&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;UNKNOWN&lt;/span&gt;&lt;span class="o"&gt;;&lt;/span&gt;
    &lt;span class="o"&gt;}&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Note that we pre-fill the array with &lt;code&gt;UNKNOWN&lt;/code&gt; to avoid the cost of a &lt;code&gt;if (result == null)&lt;/code&gt; at each call. Do a bit more upfront to do a lot less later.&lt;/p&gt;
&lt;p&gt;The benchmark of array lookup, with the loop with fast path checks for comparison:&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;Benchmark               (code)  Mode  Samples   Score  Score error  Units
loopFastPath                 0  avgt       10   3.044        0.092  ns/op
loopFastPath                 1  avgt       10   3.040        0.051  ns/op
loopFastPath               134  avgt       10  25.070        0.637  ns/op
loopFastPath               255  avgt       10  31.215        1.089  ns/op
loopFastPath              1024  avgt       10  32.464        0.930  ns/op

lookupArray                  0  avgt       10   3.061        0.126  ns/op
lookupArray                  1  avgt       10   3.048        0.127  ns/op
lookupArray                134  avgt       10   3.070        0.084  ns/op
lookupArray                255  avgt       10   3.035        0.113  ns/op
lookupArray               1024  avgt       10   3.034        0.113  ns/op
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;There we are! Constant time lookup, no allocation, and as fast as the article's solution for values in the fast path.&lt;/p&gt;
&lt;p&gt;Note: the code on GitHub has &lt;a href="https://github.com/swallez/jmh-couchbase-keyvaluestatus/blob/master/src/main/java/net/bluxte/experiments/couchbase_keyvalue/KeyValueStatus.java#L219"&gt;two more experiments&lt;/a&gt; (array lookup with a try/catch, and a large switch statement) but they don't give better results.&lt;/p&gt;
&lt;h2 id="conclusion"&gt;Conclusion&lt;/h2&gt;
&lt;p&gt;What can be learned from both articles is that benchmarks are awesome tools to actually measure improvements, but they can also be dangerous, by making people short-sighted and optimize only part of the problem, even on a 10-line code block.&lt;/p&gt;
&lt;p&gt;Before going into nano-optimization driven by micro-benchmarks, take a step back and ask yourself "What is the problem I have to solve? How can I do it differently?"&lt;/p&gt;
&lt;p&gt;And be curious, look at how things are implemented under the covers, and go down the rabbit hole once in a while to really understand how things work. You will learn a lot, and it will most certainly change the way you solve problems.&lt;/p&gt;
&lt;p&gt;Ah, and don't forget at the end to check that you actually &lt;em&gt;solved&lt;/em&gt; the original problem :-)&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Sat, 26 Nov 2016 11:02:10 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2016-11-26:musings/2016/11/26/micro-benchmarks-can-make-you-short-sighted/</guid></item><item><title>'Afternoon hack: a USB foot keyboard'</title><link>http://bluxte.net/musings/2016/07/29/usb-foot-keyboard/</link><description>&lt;p&gt;This post explains a quick afternoon hack to turn a foot pedal
controller for music synthesizers into a programmable USB foot keyboard.&lt;/p&gt;
&lt;p&gt;A couple of weeks ago, for a personal project, my wife needed to
manually transcribe many hours of interview recordings. Text-to-speech
software were failing miserably both because of the people's strong
local accent and poor recording quality. To ease the task she used the
free version of &lt;a href="http://www.nch.com.au/scribe/"&gt;Express Scribe&lt;/a&gt;, a nice
dedicated application with a powerful transport bar that works exactly
like 20th century tapes: rewind/forward while playing back, slow down/up
playback speed, etc.&lt;/p&gt;
&lt;p&gt;How cool would it be to control this with the feet, so that she could
have her hands free for typing? At least his was the dubious excuse I
needed for a hack I had been thinking about for quite some time :-)&lt;/p&gt;
&lt;figure class="xrow"&gt;&lt;img src="http://bluxte.net/musings/2016/07/29/usb-foot-keyboard/foot-keyboard.jpg" class="xcol-md-offset-2 xcol-md-8 xcol-sm-offset-1 xcol-sm-10" alt="Korg EC5 foot controller"&gt;&lt;/figure&gt;

&lt;p&gt;&lt;strong&gt;The hardware&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The &lt;a href="http://www.korg.com/products/accessories/ec_5/"&gt;Korg EC5&lt;/a&gt; is a
sturdy 5 pedals foot controller aimed at Korg's synthesizers. It's a
dedicated device that has no MIDI nor USB interface. Its 6 pin connector
is just wires to the 5 pedal switches and a common ground. We'll turn it
into a programmable 5 keys USB "keyboard". Here's the pin layout of the
EC5 output connector:&lt;/p&gt;
&lt;p&gt;&lt;img alt="Korg EC5 foot controller" src="http://bluxte.net/musings/2016/07/29/usb-foot-keyboard/Korg-EC5-rear.png" /&gt;&lt;/p&gt;
&lt;figure class="row"&gt;&lt;img src="http://bluxte.net/musings/2016/07/29/usb-foot-keyboard/pinout.svg" class="col-lg-offset-3 col-lg-6 col-sm-offset-2 col-sm-8" alt="Korg EC5 pinout"&gt;&lt;/figure&gt;

&lt;p&gt;I am a big fan of &lt;a href="https://www.pjrc.com/teensy/"&gt;Teensy
microcontrollers&lt;/a&gt; (which I buy from my
friends at &lt;a href="http://snootlab.com/lang-en/79-teensy"&gt;Snootlab&lt;/a&gt;): this
cheap tiny thing has a lot of inputs and outputs and can emulate almost
any USB device: mouse, joystick, keyboard, MIDI devices, and even flight
simulator controls! We just need to cut the EC5 cable and solder the
wires on the Teensy's ground and digital inputs 0 to 4. That's all there
is for the hardware part!&lt;/p&gt;
&lt;p&gt;&lt;img alt="Teensy microcontroller" src="http://bluxte.net/musings/2016/07/29/usb-foot-keyboard/teensy.jpg" /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;The code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The software to turn pedal switches into USB key presses is simple, but
requires to understand basic concepts of digital I/O. Discussing with my
colleagues, I realized that most developers have learned digital
electronic basics during their studies, but often quickly forgot about
it. This is what actually motivated me to write this post.&lt;/p&gt;
&lt;p&gt;Here's the source code. As for all programs written with the Arduino
IDE, it's a single C++ file that instead of a standard &lt;code&gt;main()&lt;/code&gt; has two
methods: &lt;code&gt;setup()&lt;/code&gt; to initialize the system, and &lt;code&gt;loop()&lt;/code&gt; that is called
over and over and where we read sensors, activate outputs, send data,
etc.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="cm"&gt;/*&lt;/span&gt;
&lt;span class="cm"&gt; * Korg EC5 mapping to control Express Scribe&lt;/span&gt;
&lt;span class="cm"&gt; * You must select &amp;quot;Keyboard&amp;quot; from the &amp;quot;Tools &amp;gt; USB Type&amp;quot; menu in the Arduino IDE&lt;/span&gt;
&lt;span class="cm"&gt; */&lt;/span&gt;

&lt;span class="cp"&gt;#include&lt;/span&gt; &lt;span class="cpf"&gt;&amp;lt;Bounce.h&amp;gt;&lt;/span&gt;&lt;span class="cp"&gt;&lt;/span&gt;

&lt;span class="c1"&gt;// Create a Bounce object for each pedal. The Bounce object&lt;/span&gt;
&lt;span class="c1"&gt;// automatically deals with contact chatter or &amp;quot;bounce&amp;quot;, and&lt;/span&gt;
&lt;span class="c1"&gt;// makes detecting changes very simple.&lt;/span&gt;
&lt;span class="n"&gt;Bounce&lt;/span&gt; &lt;span class="n"&gt;pedalA&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Bounce&lt;/span&gt; &lt;span class="n"&gt;pedalB&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Bounce&lt;/span&gt; &lt;span class="n"&gt;pedalC&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Bounce&lt;/span&gt; &lt;span class="n"&gt;pedalD&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="n"&gt;Bounce&lt;/span&gt; &lt;span class="n"&gt;pedalE&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;Bounce&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="mi"&gt;10&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;We start by creating 5 debouncers, one for each key, with a 10
milliseconds delay. Debouncing is mandatory in the hardware world: when
a switch changes state, the measured value can be randomly 0 or 1 for a
brief period of time, until the contact is stabilized. This debouncer is
a great example of the amazing Arduino ecosystem, that provides a lot of
components with a simple API, even if under the hood the implementation
may be really tricky.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="nf"&gt;byte&lt;/span&gt; &lt;span class="n"&gt;playMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;false&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;setup&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Configure the pins for input mode with pullup resistors.&lt;/span&gt;
  &lt;span class="nf"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;INPUT_PULLUP&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;INPUT_PULLUP&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;2&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;INPUT_PULLUP&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;3&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;INPUT_PULLUP&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="nf"&gt;pinMode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;4&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kc"&gt;INPUT_PULLUP&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;The calls to
&lt;a href="https://www.arduino.cc/en/Reference/PinMode"&gt;pinMode()&lt;/a&gt; configure the
pins as digital inputs and activate the internal pull-up resistor. What
is this, and why is it needed?&lt;/p&gt;
&lt;p&gt;When a switch is closed, its pin is connected the ground, and we measure
&lt;code&gt;LOW&lt;/code&gt; (0 Volt). If the switch is open, its pin is "floating" and the
measure is unpredictable. To have a stable value when the switch is
open, we connect its output to Vcc (3.3 V for the Teensy) using a
resistor. This has the effect of "pulling up" the voltage of the pin to
a stable value that can be measured. The call to
&lt;a href="https://www.arduino.cc/en/Reference/DigitalRead"&gt;digitalRead()&lt;/a&gt; will
then return &lt;code&gt;HIGH&lt;/code&gt; if the measured voltage is higher than 2 Volt. Note
that we cannot simply connect the input pin to Vcc, as it would create a
short circuit when the switch is closed!&lt;/p&gt;
&lt;p&gt;This value of 2 Volt comes from the fact that the pull-up resistor is
combined with impedance of the microcontroller's analog to digital
converter, which effectively creates a voltage divider.&lt;/p&gt;
&lt;p&gt;The figure below outlines this:&lt;/p&gt;
&lt;figure class="row"&gt;&lt;img src="http://bluxte.net/musings/2016/07/29/usb-foot-keyboard/pull-up.svg" class="col-lg-offset-3 col-lg-6 col-sm-offset-2 col-sm-8" alt="Use of a pull-up resistor"&gt;&lt;/figure&gt;

&lt;p&gt;If you want the nitty gritty details about calculating the value of
pull-up resistors, read this &lt;a href="https://learn.sparkfun.com/tutorials/pull-up-resistors"&gt;Sparkfun
tutorial&lt;/a&gt; or
this &lt;a href="http://www.ti.com/lit/an/slva485/slva485.pdf"&gt;reference
documentation&lt;/a&gt; from Texas
Instruments.&lt;/p&gt;
&lt;p&gt;This pull-up resistor pattern is so common that microcontrollers now
have embedded pull-up resistors that can be activated via software. This
is what &lt;code&gt;INPUT_PULLUP&lt;/code&gt; does: configure the pin as input, and activate
the internal pull-up resistor so that we have a stable and measurable
voltage when the switch is open, without requiring an external resistor.
This makes less parts and also avoids mistakes while prototyping.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;&lt;span class="kt"&gt;void&lt;/span&gt; &lt;span class="nx"&gt;loop&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Let pedal switches debouncers update their state.&lt;/span&gt;
  &lt;span class="n"&gt;pedalA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;pedalB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;pedalC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;pedalD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
  &lt;span class="n"&gt;pedalE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;update&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;This the beginning of the loop that will continuously track the change
in pedal switches states and send USB key presses whenever changes
happen.&lt;/p&gt;
&lt;div class="highlight"&gt;&lt;pre&gt;&lt;span&gt;&lt;/span&gt;  &lt;span class="c1"&gt;// Debouncers track &amp;quot;falling&amp;quot; and &amp;quot;rising&amp;quot; edges on the signal,&lt;/span&gt;
  &lt;span class="c1"&gt;// that are triggered by pedal press and release.&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fallingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;press&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalA&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;risingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F3&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fallingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;press&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalB&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;risingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F4&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fallingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c1"&gt;// Flip play mode&lt;/span&gt;
    &lt;span class="n"&gt;playMode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="o"&gt;!&lt;/span&gt;&lt;span class="n"&gt;playMode&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;press&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playMode&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nl"&gt;KEY_F5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;KEY_F6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalC&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;risingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;playMode&lt;/span&gt; &lt;span class="o"&gt;?&lt;/span&gt; &lt;span class="nl"&gt;KEY_F5&lt;/span&gt; &lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="n"&gt;KEY_F6&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fallingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;press&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalD&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;risingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F7&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;fallingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;press&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;pedalE&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;risingEdge&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt; &lt;span class="nf"&gt;Keyboard&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;release&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;KEY_F8&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/pre&gt;&lt;/div&gt;


&lt;p&gt;Express Scribe allows defining keyboard shortcuts for its actions. The
default configuration doesn't include mappings for everything we want to
control with the feet, so we've configured it as follows:&lt;/p&gt;
&lt;ul&gt;
&lt;li&gt;F3 : reduce playback speed, mapped to pedal A&lt;/li&gt;
&lt;li&gt;F4 : rewind, mapped to pedal B&lt;/li&gt;
&lt;li&gt;F5 : play, mapped to pedal C&lt;/li&gt;
&lt;li&gt;F6 : pause, mapped to pedal C&lt;/li&gt;
&lt;li&gt;F7 : fast forward, mapped to pedal D&lt;/li&gt;
&lt;li&gt;F8 : increase playback speed, mapped to pedal E&lt;/li&gt;
&lt;/ul&gt;
&lt;p&gt;All pedal switches except pedal C have the same behavior: when the pedal
is pressed (falling edge of the measured value) we send a key press
event. Conversely when there the pedal is released (rising edge) we send
a key release event.&lt;/p&gt;
&lt;p&gt;Pedal C (the middle pedal) is a single command for both play and pause,
which is much more comfortable than having to move the foot to play and
pause. This is why pressing pedal C send either F5 or F6 depending on
the value of "playMode" which is flipped at each press of this pedal.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Conclusion&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Writing this article took a lot more time than actually doing this
little hack! But I hope to have demystified the basics of digital input
with microcontrollers. If you know how to program, you just need some
basic soldering skills to start hacking. And this also is &lt;a href="https://learn.adafruit.com/adafruit-guide-excellent-soldering?view=all"&gt;easy to
learn&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Now how about the usefulness of this for my wife? Well... it turned out
that coordinating feet and hand movement isn't something you master
instantly, and in the end she ended up using mostly the function keys on
the Mac's keyboard...&lt;/p&gt;
&lt;p&gt;Oh well, that was a fun experiment nonetheless and I now have a new toy
to control programs in unusual ways. I have some sort of track record
here, having used a Wii remote to draw virtual grafittis on a wall, a
Kinect to draw 3D virtual wireframes with an augmented reality headset,
and other weird things!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Fri, 29 Jul 2016 11:21:00 +0200</pubDate><guid isPermaLink="false">tag:bluxte.net,2016-07-29:musings/2016/07/29/usb-foot-keyboard/</guid></item><item><title>Blog.reboot()</title><link>http://bluxte.net/musings/2016/06/18/blog-reboot/</link><description>&lt;p&gt;This blog is now a static website powered by the
&lt;a href="http://blog.getpelican.com/"&gt;Pelican&lt;/a&gt; generator. It's the 3rd major
change since I &lt;a href="/musings/"&gt;started blogging in 2002&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;It began with &lt;a href="https://en.wikipedia.org/wiki/Movable_Type"&gt;Movable
Type&lt;/a&gt;, a Perl blogging tool.
There wasn't much choice at that time, and it did the job even if I did
not like Perl (and still do not). In 2009 I &lt;a href="/musings/2009/04/09/my-new-web-site-drupal-powered/"&gt;switched to Drupal
6&lt;/a&gt;, which allowed
me to have a nicer visual layout and have more control on the
navigation, starting with clean URLs.&lt;/p&gt;
&lt;p&gt;Now for a blog I don't need a full blown CMS for dynamic web pages,
with the operational burden what comes with it. Also, the content
writing UI in Drupal isn't that great (or wasn't, since I stayed with
Drupal 6), and you ultimately end up writing HTML, even if hidden behind
a fancy WYSIWYG editor. So much for semantic markup and separation of
content and presentation.&lt;/p&gt;
&lt;p&gt;Over time, the combination of Twitter's 140 characters instant
gratification and a clunky writing UI led this blog to be really
neglected. Now I have things to share that don't fit in a tweet!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Going static&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;So it was time for a change, and I was urged in that by my two sons
&lt;a href="http://blog.kangz.net/"&gt;Corentin&lt;/a&gt; and
&lt;a href="https://blog.twal.org/"&gt;Théophile&lt;/a&gt; who started a "one blog post a
month" challenge. Instead of just writing a blog post, I decided to
reboot this blog so that the urge or writing would not be hindered by an
unfriendly tool.&lt;/p&gt;
&lt;p&gt;The 3 of us are now running our blogs with the Pelican static blog
generator. I also did some quite extensive tests with
&lt;a href="https://getnikola.com/"&gt;Nikola&lt;/a&gt;, but in the end Pelican won because of
its larger theme library that allowed me to experiment faster. Nikola's
speed and live reloading while editing content are definitely better
than Pelican's though, and now that I have settled on a theme I may
come back to it.&lt;/p&gt;
&lt;p&gt;Why not using the popular &lt;a href="https://jekyllrb.com/"&gt;Jekyll&lt;/a&gt; or
&lt;a href="https://gohugo.io/"&gt;Hugo&lt;/a&gt;? The main reason is that I want to store my
content in a format that is stable, well defined and with enough builtin
features for documents that go beyond the simple set of headings, text
and code snippets. I want to own my content, and I want it to last.&lt;/p&gt;
&lt;p&gt;This rules out Markdown, since every tool comes with its own dialect and
extensions, even if some are more popular than others, and even with the
&lt;a href="http://commonmark.org/"&gt;CommonMark&lt;/a&gt; initiative. Same for
&lt;a href="https://en.wikipedia.org/wiki/Textile_%28markup_language%29"&gt;Textile&lt;/a&gt;
who also seems to be falling into oblivion.&lt;/p&gt;
&lt;p&gt;The remaining contenders were
&lt;a href="http://docutils.sourceforge.net/rst.html"&gt;reStructuredText&lt;/a&gt; and
&lt;a href="http://www.methods.co.nz/asciidoc/"&gt;AsciiDoc&lt;/a&gt;, who both have a formal
specification. Their reference implementation is written in Python, so
choosing a Python-based generator seemed a natural choice. Sure, other
generators can use RestructuredText and AsciiDoc by forking external
processes, but having the parser within the generators allows for
tighter integration and greater generation speed. AsciiDoc also has the
great AsciiDoctor Ruby implementation, but I'm no rubyist.&lt;/p&gt;
&lt;p&gt;ReStructuredText has fewer syntactic artifacts than AsciiDoc, meaning
less cognitive load for the same document complexity. So I'll use
reStructuredText as the main writing format, knowing that the great
&lt;a href="http://pandoc.org/"&gt;Pandoc&lt;/a&gt; can do wonders converting from one syntax
to another.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setting up the new blog&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The full configuration is &lt;a href="https://github.com/swallez/bluxte-blog-pelican"&gt;published on
GitHub&lt;/a&gt;. Actual content
and deployment configurations are in a separate private repository.&lt;/p&gt;
&lt;p&gt;The theme is based on &lt;a href="http://startbootstrap.com/template-overviews/clean-blog/"&gt;StartBootstrap's Clean
Blog&lt;/a&gt; and its
&lt;a href="https://github.com/gilsondev/pelican-clean-blog"&gt;Pelican
implementation&lt;/a&gt; which I
modified slightly. I still have to clean up the CSS and trim down
Bootstrap to what's actually needed.&lt;/p&gt;
&lt;p&gt;&lt;a id="banners"&gt;&lt;/a&gt;
The banner images are randomly generated from a set of banner pictures
(taken by me), unless I explicitly specify one in the post's metadata.
I had this in the Drupal-based version, and love it since it gives a
nice visual touch to pages without requiring scouting for an appropriate
picture when none comes to mind quickly (choosing images is hard!)&lt;/p&gt;
&lt;p&gt;The old content is still in HTML, and was extracted from Drupal with a
tiny scraping script. It was actually easier than getting it out of the
database, since over time I used various Drupal output formats. I'll
progressively go through all past 369 (!) articles to convert them
(again with Pandoc), clean up broken links and harmonize the layout.&lt;/p&gt;
&lt;p&gt;The comments are now powered by &lt;a href="https://posativ.org/isso/"&gt;Isso&lt;/a&gt;, a
self-hosted Disqus clone, and I have imported the old comments from
Drupal with a custom Python script. Again, I want to own my content, and
comments are an integral part of it.&lt;/p&gt;
&lt;p&gt;Publishing is not yet automated, and won't be until I a become a really
proficient writer. Running a makefile once in while is good enough for
now!&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Hosting&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;And since this is a reboot, I also completely overhauled the
infrastructure. This blog has been running for ages on a bare metal
server, which I carefully nurtured and updated. Devops and immutable
infrastructure are all the rage these days, so I used at home the same
techniques I use at work: this blog is now running (warning: buzzwords
ahead!) as a set of Docker containers managed with a simple docker
compose file. The containers are running the
&lt;a href="https://traefik.io/"&gt;Træfik&lt;/a&gt; reverse proxy in front of the
&lt;a href="https://caddyserver.com/"&gt;Caddy&lt;/a&gt; file server and the
&lt;a href="https://posativ.org/isso/"&gt;Isso&lt;/a&gt; comment server.&lt;/p&gt;
&lt;p&gt;If you don't know Træfik and Caddy, you should definitely have a look:
they took a fresh start to web servers, taking into account the latest
evolutions of the web: you get instant HTTP/2 and painless free SSL with
&lt;a href="https://letsencrypt.org/"&gt;Let's encrypt&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;The server is a 3€/mo VPS which I can setup with a single command. Now I
hear you say "if this is a static blog, why not using Github Pages"?
Well, call me a masochist, but I actually enjoy tweaking my server.
I've been doing it for more than a decade, and it's nice to have your
own playground where you can experiment and break things!&lt;/p&gt;
&lt;p&gt;Now enough with this meta-post. I've started collecting ideas and
drafts for real content in this new shiny home!&lt;/p&gt;</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Sat, 18 Jun 2016 18:12:00 +0200</pubDate><guid isPermaLink="false">tag:bluxte.net,2016-06-18:musings/2016/06/18/blog-reboot/</guid></item><item><title>Efficient storage of non-periodic time series with MongoDB</title><link>http://bluxte.net/musings/2015/01/21/efficient-storage-non-periodic-time-series-mongodb/</link><description>
  &lt;p&gt;&lt;b&gt;TL;DR:&lt;/b&gt; this post explains the MongoDB storage structure we use at &lt;a href="http://www.actoboard.com/"&gt;Actoboard&lt;/a&gt; to efficiently store non periodic time series. Storing one Mongo document for each data point is woefully inefficient, so we store them in fixed-size segments, which speeds things up by more than an order of magnitude.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;MongoDB makes the developer's life easier&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;When we started Actoboard, we decided to use MongoDB to store all our data. I already used it successfully on several projects, and it makes things a lot easier compared to an SQL database when you have a rich data model using a lot of polymorphic structures. You don't have this impedance mismatch between application objects and tables that has produced these object-relational monsters we've loved to hate.&lt;/p&gt; 
&lt;p&gt;MongoDB is nice for all our configuration data (data sources, widgets, etc): JSON documents are perfect for these fat polymorphic configuration objects, the volume of such data is limited, and the load is mostly read, avoiding the lock problems Mongo has in write-heavy scenarios.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Time series need special attention&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;Time series data is a different beast, with a write-mostly load of tiny objects consisting of dataset id, timestamp and value. The naive approach of storing each data point as a tiny document will yield poor write performance, as the database has to allocate space for every tiny document holding a data point and add it to the index, which will be almost as large as the actual data.&lt;/p&gt; 
&lt;p&gt;Read performance will be bad too as the data for a series will be spread in many places on disk, requiring lots of disk seeks when reading a time slice. Deletion of expired data will also create lots of holes on disk, increasing load on the database's space allocator.&lt;/p&gt; 
&lt;p&gt;We could have used a dedicated database to store time series, but when we started the project with a very small team (1.5 people) we tried to limit the number of moving parts in the architecture. We're ready however to switch to &lt;a href="http://cassandra.apache.org"&gt;Cassandra&lt;/a&gt; when load becomes a problem: its P2P architecture and log-structured storage naturally avoids write contention and stores data on disk in chronological order. But we're not there yet.&lt;/p&gt; 
&lt;p&gt;The solution is therefore to store many data points in a single MongoDB document. This document has to be pre-allocated (filled with empty values) to avoid its size to change as new data is added, causing it to be relocated on disk. Storing a new data point then consists in doing in-place updates of an empty slot in the document.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;The case of non periodic time series&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;There are &lt;a href="http://blog.pythonisito.com/2012/09/mongodb-schema-design-at-scale.html"&gt;many&lt;/a&gt; &lt;a href="http://blog.mongodb.org/post/65517193370/schema-design-for-time-series-data-in-mongodb"&gt;blog posts&lt;/a&gt; explaining how to store time series data, but they assume periodic sampling or predefined periodic aggregations. At Actoboard we have widely varying data collection rates ranging from once every minute to once a day. Users can also push values to their custom data sources whenever they want. So we needed something different.&lt;/p&gt; 
&lt;p&gt;Our time series data is stored in “value segments” containing a fixed number of data points. A segment has the following properties:&lt;/p&gt; 
&lt;ul&gt; 
 &lt;li&gt;the time series identifier (we use 64 bits integers),&lt;/li&gt; 
 &lt;li&gt;the end time of the previous segment (more on this later)&lt;/li&gt; 
 &lt;li&gt;the start time of the next segment (ditto),&lt;/li&gt; 
 &lt;li&gt;data point times, as an array of 64 bits timestamps,&lt;/li&gt; 
 &lt;li&gt;data values, as an array of 64 bits floats.&lt;/li&gt; 
&lt;/ul&gt; 
&lt;p&gt;The diagram below illustrates a series with 3 segments, the most recent one being partially filled.&lt;/p&gt; 
&lt;p&gt;&lt;/p&gt;
&lt;center&gt;
 &lt;img src="/archives/value_segments.png"&gt;
&lt;/center&gt;
&lt;p&gt;&lt;/p&gt; 
&lt;p&gt;The actual JSON object looks like this:&lt;/p&gt; 
&lt;pre&gt;
{
  "_id": NumberLong("133506131220758528"),
  "series": NumberLong("133814973280288768"),
  "owner" : NumberLong("112076101043355649"),
  "prevEnd" : NumberLong("1390410338000"),
  "nextStart" : NumberLong("1390485108000"),
  "time" : [ NumberLong("1390483902000"), NumberLong("1390483299000"), … ],
  "value" : [ 24.5, 26.32, … ],
  // other housekeeping properties
}

&lt;/pre&gt;
&lt;p&gt; Because of this layout, we’ve put a strong constraint on our time series storage: data points can only be stored in chronological order. Out of order arrival is not allowed to avoid having to insert a datapoint into a filled interval, possibly leading to lots of segment manipulation. In practice this has never been a problem.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Initializing a new segment&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;When a new segment is created, its time and value arrays are pre-allocated with 160 zeroes. We calculated this length as being the maximum number of data points that can be stored in 4096 bytes, once encoded in BSON. &lt;/p&gt; 
&lt;p&gt;This 4 KiB size was chosen because MongoDB uses a &lt;a href="http://docs.mongodb.org/manual/core/storage/#power-of-2-allocation"&gt;power-of-two space allocation strategy&lt;/a&gt;, and this is also the standard Linux memory page size. Since MongoDB data files are memory-mapped, matching the page size uses the available RAM more efficiently.&lt;/p&gt; 
&lt;p&gt;On a new segment, the “prevEnd” value is set to the latest timestamp of the previously active segment (or the current timestamp if there’s none). Its “nextStart” is set to MAX_LONG (far far away in the future). More on this in the section on querying below.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Writing a new data point&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;When new data arrives, we need to know in which segment it should be written to. This is the role of a higher-level “series” object, which contains the active segment’s identifier and the next position to write to in this segment.&lt;/p&gt; 
&lt;p&gt;Time series object:&lt;/p&gt; 
&lt;pre&gt;
{
  "_id" : NumberLong("133814973280288768"),
  "lastDate" : NumberLong("1419347899000"),
  "lastValue" : 27.2,
  "segmentId" : NumberLong("254795601416290304"),
  "segmentPtr" : 121
}

&lt;/pre&gt;
&lt;p&gt; In the nominal case, writing requires two database updates.&lt;/p&gt; 
&lt;p&gt;The first update decrements the segment pointer in the time series object and returns the new value. To ensure chronological order, we add the new data point’s timestamp as a query parameter, to prevent any update if it’s not posterior to the last one written.&lt;/p&gt; 
&lt;pre&gt;
var series = db.TimeSeries.findAndModify({
  query: { _id: seriesId, lastDate: { $lt: time }},
  update: { $set: { lastValue: value, lastDate: time }, $inc: { segmentPtr: -1 }},
  new: true // return the modified document
})

&lt;/pre&gt;
&lt;p&gt; The result of this operation is an updated object, with the segment index position to write to. We can then perform our second update, storing the data at the correct place:&lt;/p&gt; 
&lt;pre&gt;
var fields = {};
fields["time." + series.segmentPtr] = timestamp;
fields["value." + series.segmentPtr] = value;

db.ValueSegments.update(
  { _id: series.segmentId },
  { $set: fields }
);

&lt;/pre&gt;
&lt;p&gt; Now why decrementing the pointer, and not incrementing it? We initialize the pointer with the array’s length. So when the decrement operation returns a negative value, we know that the current segment is full and we must create a new one, without having to care about the actual array length. Fewer magic numbers in the code mean less bugs.&lt;br&gt; Creating a new segment is the non-nominal case that requires additional writes. It only happens once every 160 values.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Dealing with non ACIDity&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;MongoDB operations are atomic only at the document level. So what happens if the system crashes once we’ve updated the segment pointer but haven’t yet written the data? We end up with an empty data point in the value segment that has a zero timestamp. We deal with it at the application level by just ignoring such data points.&lt;/p&gt; 
&lt;p&gt;Also the application may crash after we’ve decremented the pointer and found that a new segment was created, but before it was actually written. In that case, decrementing again the pointer will yield numbers less than -1. Testing for negative values and not just -1 to create a new segment solves the problem.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Querying data&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;Querying time series data is always done with a time range, particularly with non-periodic time series, since we can’t know the exact time where a data point exists. However in order to draw the series in a given [tmin, tmax] range, we need to also get the data points that are immediately &lt;em&gt;outside&lt;/em&gt; of this range, as depicted below:&lt;/p&gt; 
&lt;p&gt;&lt;/p&gt;
&lt;center&gt;
 &lt;img src="/archives/query_range.png"&gt;
&lt;/center&gt;
&lt;p&gt;&lt;/p&gt; 
&lt;p&gt;Because of our layout, we fetch entire values segments (160 data points) from the database. Now to get the immediate outside data points, we can’t just query the segments whose data points are in the [tmin, tmax] range.&lt;/p&gt; 
&lt;p&gt;This is why we store the &lt;em&gt;outer timestamps&lt;/em&gt; (previous segment end time and next segment start end time) in a value segment. This allows writing a query that returns segments containing data points right before or right after the wanted time range. Our query is then:&lt;/p&gt; 
&lt;pre&gt;
db.ValueSegments.find(
  { series: seriesId, prevEnd: { $lte: tmin}, nextStart: { $gte: tmax }},
  { sort: { prevEnd: 1 }}
)

&lt;/pre&gt;
&lt;p&gt; We then get a set of sorted value segments, and we feed their data points into a pipeline that filters, transforms and aggregates according to the user’s graph configuration.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Performance&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;Our first tests using the naive approach of 1 document per data point yielded abysmal performance, in the 500 inserts/sec on our integration server.&lt;/p&gt; 
&lt;p&gt;With this new layout, things are much better, with about 10k inserts/sec. Not bad! Database size is also way smaller because the number of entries in the index has been divided by 160!&lt;/p&gt; 
&lt;p&gt;We only achieved this number after &lt;a href="https://github.com/bguerout/jongo/pull/146"&gt;fixing a bug in Jongo&lt;/a&gt;, a thin layer on top of the Java MongoDB driver that allows using the mongo shell syntax to talk to the database. This bug was causing some integer values conversion that led to changing the BSON document layout, defeating the purpose of our value segments.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;This may all sound quite complicated, but the code to implement this is rather small and straightforward. The hard part was finding the prevEnd/nextStart trick to fetch the outer data points with no additional requests.&lt;/p&gt; 
&lt;p&gt;Achieving 10k inserts/sec on a non-sharded setup is more than enough while our user base is still small, even more considering that we rate limit inserts to one per minute, and most of the metrics we collect are updated once every 10 minutes.&lt;/p&gt; 
&lt;p&gt;And on top of this time series storage, most metrics have an input filter that ensures we only write to the database when the metric value has actually changed, further reducing insertion rate and storage requirements. No need to write the same Twitter follower count every 10 minutes if it hasn’t changed!&lt;/p&gt;
</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Wed, 21 Jan 2015 18:20:00 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2015-01-21:musings/2015/01/21/efficient-storage-non-periodic-time-series-mongodb/</guid></item><item><title>GitHub hack: a common security flaw in webapp frameworks</title><link>http://bluxte.net/musings/2012/03/08/github-hack-common-security-flaw-webapp-frameworks/</link><description>
  &lt;p&gt;&lt;a href="http://chrisacky.posterous.com/github-you-have-let-us-all-down"&gt;GitHub has faced a spectacular hack&lt;/a&gt;: a disappointed developer has exploited a weakness in Ruby on Rails to gain commit access to the Rails master branch and &lt;a href="https://github.com/rails/rails/issues/5239"&gt;create issues in the future&lt;/a&gt;. As a result, GitHub asks us to confirm our ssh keys, but this can have been used to change almost any data in the system.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;How's it possible?&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;This weakness comes from the mass assignment feature in Rails. To ease development and increase productivity, Rails allows an object to be filled with any http request parameter whose name match an attribute of the object. All is well when people use the forms provided by your web pages, because they only send parameters for attributes that &lt;em&gt;you&lt;/em&gt; (the developer) want to change. Now things are different when someone forges a request: your object is wide open, and they can change &lt;em&gt;all&lt;/em&gt; of its attributes.&lt;/p&gt; 
&lt;p&gt;If you have a User class with properties &lt;code&gt;id&lt;/code&gt;, &lt;code&gt;name&lt;/code&gt;, &lt;code&gt;password&lt;/code&gt;, &lt;code&gt;role&lt;/code&gt;, then a user with role "visitor" can upgrade himself to "administrator" simply using the profile edition URL. Or change the password of another user to get access to his account by changing the id value, or... etc.&lt;/p&gt; 
&lt;p&gt;Most modern web frameworks have this mass assignment feature. They allow the developer to restrict the assignable attributes by means of whitelists or blacklists, but &lt;b&gt;most if not all of them have it wide open by default&lt;/b&gt;. This is a comfortable developer feature, but how many of them will even think of protecting their model?&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;A couple of examples&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;Rails allows &lt;a href="http://edgeguides.rubyonrails.org/security.html#mass-assignment"&gt;whilelisting and blacklisting&lt;/a&gt; in the model classes. It also has scoped protection, which is useful since the assignment constraints are different e.g. in a profile edition page and a user administration page.&lt;/p&gt; 
&lt;p&gt;In the Java world, &lt;a href="http://static.springsource.org/spring/docs/3.1.x/spring-framework-reference/html/mvc.html"&gt;Spring MVC&lt;/a&gt; is also wide open by default. It allows white/black listing, but this is defined at the controller level. It is rather cumbersome to use, since you have to make sure each and every controller has a &lt;a href="http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/web/bind/annotation/InitBinder.html"&gt;&lt;code&gt;@InitBinder&lt;/code&gt;&lt;/a&gt; method that correctly configures the binder using &lt;a href="http://static.springsource.org/spring/docs/3.1.x/javadoc-api/org/springframework/validation/DataBinder.html#setAllowedFields%28java.lang.String...%29"&gt;&lt;code&gt;DataBinder.setAllowedFields()&lt;/code&gt;&lt;/a&gt;.&lt;/p&gt; 
&lt;p&gt;&lt;a href="http://www.playframework.org/"&gt;Play! Framework&lt;/a&gt; is also wide open by default (told you, all of them!), but has an easy scoped blacklisting with the &lt;a href="http://www.playframework.org/documentation/1.2.4/controllers#nobinding"&gt;@NoBind&lt;/a&gt; annotation on model attributes. Whitelisting would be more secure though.&lt;/p&gt; 
&lt;p&gt;It is to be noted that component-oriented frameworks like &lt;a href="http://wicket.apache.org/"&gt;Wicket&lt;/a&gt; should not suffer from this mass assignment issue, since they have a separate page model that isolates domain objects from the request. This comes however with additional complexity and bigger server side sessions.&lt;/p&gt; 
&lt;p&gt;And finally, this mass assignment issue is not limited to page controllers but also affects less visible elements, such as JSON encoder/decoders where mass assignment is the norm. Here again, JSON libraries like &lt;a href="http://jackson.codehaus.org/"&gt;Jackson&lt;/a&gt;, &lt;a href="http://code.google.com/p/google-gson/"&gt;GSon&lt;/a&gt;, &lt;a href="http://flexjson.sourceforge.net/"&gt;Flexjson&lt;/a&gt;, etc make no restriction on the attribute names by default, and so the nice REST API that you have designed may well be a giant open door for attackers.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;Conclusion&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;This hack on GitHub has given a lot of visibility to a problem that is largely present in many of today's web framework, which have traded comfort for security by default. We may see a lot of exploits of this flaw in the coming weeks on websites using a large variety of frameworks.&lt;/p&gt; 
&lt;p&gt;So make sure your webapp is not wide open, and let's hope framework developers will consider that security by default should have priority over comfort if the price to pay is to add a couple of annotations on the model classes.&lt;/p&gt;
</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Thu, 08 Mar 2012 12:55:00 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2012-03-08:musings/2012/03/08/github-hack-common-security-flaw-webapp-frameworks/</guid></item><item><title>My 2011: a year like no other</title><link>http://bluxte.net/musings/2012/01/01/my-2011-year-no-other/</link><description>
  &lt;p&gt;This blog has been mostly silent in 2011. Blame both &lt;a href="http://twitter.com/bluxte" title="My tweets"&gt;Twitter&lt;/a&gt; that makes capturing quick thoughts so easy and a busy year as I started my freelance business. But a new year is starting, and along with the traditional wishes I owe an update to the people that still look around here. There have been many important events in the world this year, but I will talk about the selfish me, since this year has been like no other in my professional life.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;I'm my own boss!&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;When &lt;a href="http://bluxte.net/musings/2011/01/10/new-year-new-job" title="New year, new job (10 January 2011)"&gt;I decided to go freelance&lt;/a&gt;, I thought it would be for a limited time while I worked on setting up a new startup project. It turned out this was a rather ambitious project, one of the kind I was a bit tired of, requiring a lot of work before reaching out to the world, and that the people I had planned to build it with were not the right ones for this kind of venture.&lt;/p&gt; 
&lt;p&gt;So I started to grow my freelance business, working 3 days a week architecting and developing the backend systems of a new &lt;acronym title="Machine to Machine"&gt;M2M&lt;/acronym&gt; solution using J2EE (mostly Jetty and Spring), &lt;a href="http://www.hazelcast.com/"&gt;Hazelcast&lt;/a&gt; and MongoDB, and doing some short expert consulting gigs in various domains: data collection architecture, mobile geolocation app strategy, search engines, etc. I also did some fun side projects exploring &lt;a href="http://www.ac-toulouse.fr/web/65-actualites.php?actu=15217"&gt;augmented reality&lt;/a&gt; and &lt;a href="http://kinecthacks.net/interactive-building-mapping/" title="Interactive building mapping"&gt;Kinect hacks&lt;/a&gt; with my son and my friends at &lt;a href="http://tetalab.org/" title="Toulouse hackerspace"&gt;Tetalab&lt;/a&gt;, the Toulouse hackerspace.&lt;/p&gt; 
&lt;p&gt;I was also offered several interesting positions, but I didn't felt like being an employee again now, and most of them required relocating which isn't currently an option. So among others, I declined offers from Google, Facebook and even Apple who all seem to be starving for talents! Feels a bit weird to say "thanks, but no" to these big names...&lt;/p&gt; 
&lt;p&gt;I've also incorporated my freelance business for tax reasons, and the very difficult part was finding a name. After a long search and the help of &lt;a href="https://www.google.com/search?q=startup+name+generator"&gt;startup name generators&lt;/a&gt;, we settled during a family gathering on &lt;a href="http://digispoon.com/"&gt;&lt;em&gt;Digispoon&lt;/em&gt;&lt;/a&gt;. No real website for now, as I don't really need it and don't have the time to set it up. And don't ask for a long explanation for this name: Digispoon just sounds nice, has this "digi" prefix that fits well with my various digital activities, and "spoon" has this double-O that so many web companies have, including my two former employers (&lt;a href="http://www.joost.com/"&gt;Joost&lt;/a&gt; and Goojet, now rebooted as &lt;a href="http://www.scoop.it/"&gt;Scoop.it&lt;/a&gt;). A funny (or stupid) tagline could be "Add a spoonful of digital technology to your projects" :-)&lt;/p&gt; 
&lt;p&gt;If you have a nice tagline or logo idea, leave a comment!&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;New projects&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;In this period of change, two books really inspired me: &lt;a href="http://tetalab.org/" title="Untitled"&gt;The 4-hour work week&lt;/a&gt;, and &lt;a href="http://www.startupbook.net/"&gt;Start small, Stay small, a developer's guide to launching a startup&lt;/a&gt;. In rather different ways, these books opened my eyes on the fact that there are other routes than either large companies or heavily funded startups. It is perfectly possible to build a one or two persons startup and grow a business that will bring enough money to live more than comfortably. And we live a golden age for this: hosting a web site has never been so cheap, and we have highly productive toolboxes available that make possible things we barely thought about a couple of years ago.&lt;/p&gt; 
&lt;p&gt;So this is where I am now: I've met people with business ideas and skills but little or no technical knowledge, and along with my part time freelance business I'm working on these projects. These are two different projects, which makes my work week a lot more than 4 hours, but these were interesting opportunities I did not wanted to miss. Nothing to show yet, but they'll both go live in a couple of weeks.&lt;/p&gt; 
&lt;p&gt;Technically, I'm using &lt;a href="http://www.playframework.org/"&gt;Play Framework&lt;/a&gt;, &lt;a href="http://jquery.com/"&gt;jQuery&lt;/a&gt; and its countless plugins and &lt;a href="http://lesscss.org/"&gt;Less CSS&lt;/a&gt;, with MongoDB, MySQL and &lt;a href="http://lucene.apache.org/"&gt;Lucene&lt;/a&gt; to store data and Hazelcast for cluster messaging and synchronization. A highly productive mix that allows me to go straight to the problem to solve rather than having to fight with boring infrastructure boilerplate.&lt;/p&gt; 
&lt;p&gt;&lt;b&gt;2012&lt;/b&gt;&lt;/p&gt; 
&lt;p&gt;The year ahead will hopefully see these projets come to a fruitful life. Although I like it, my consulting business is more a means to eat and fund these projects than an end and who knows, maybe in 2013 I'll reach the mythical objective of working 4 hours a week and have plenty of time for all the things I've put aside because of lack of time. Not sure I'll ever reach that point though: I love technology too much!&lt;/p&gt; 
&lt;p&gt;And I promise I'll write more than a blog post a year :-)&lt;/p&gt; 
&lt;p&gt;Happy new year all!&lt;/p&gt;
</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Sun, 01 Jan 2012 13:15:00 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2012-01-01:musings/2012/01/01/my-2011-year-no-other/</guid></item><item><title>How often do you redeploy your J2EE application?</title><link>http://bluxte.net/musings/2011/01/11/how-often-do-you-redeploy-your-j2ee-application/</link><description>
  &lt;p&gt;The guys at ZeroTurnaround have published an interesting &lt;a href="http://www.zeroturnaround.com/java-ee-productivity-report-2011/"&gt;report on the development habits&lt;/a&gt; from over 1300 Java developers. One of the questions that really struck me was "&lt;em&gt;how often do you redeploy?&lt;/em&gt;"&lt;/p&gt; 
&lt;p&gt;My answer to this question is "on my development machine, never". I use &lt;a href="http://jetty.codehaus.org/jetty/"&gt;Jetty&lt;/a&gt; which is really easy to embed in a regular application. So all of the projets I work on have this tiny class in their &lt;code&gt;src/run/java&lt;/code&gt; directory:&lt;/p&gt; 
&lt;pre&gt;
package net.bluxte.project;

import org.eclipse.jetty.server.Server;
import org.eclipse.jetty.server.nio.SelectChannelConnector;
import org.eclipse.jetty.webapp.WebAppContext;

public class StartProject {
    
    public static void main(String[] args) throws Exception {
        Server server = new Server();
        SelectChannelConnector connector = new SelectChannelConnector();
        connector.setHost("127.0.0.1");
        connector.setPort(8888);
        connector.setForwarded(true);
        server.addConnector(connector);
        
        WebAppContext context = new WebAppContext("src/main/webapp", "/");
        context.setClassLoader(Thread.currentThread().getContextClassLoader());
        server.setHandler(context);
        
        server.start();
        server.join();
    }
}
&lt;/pre&gt;
&lt;p&gt; This tiny class allows me to start the server with just a single click on Eclipse's "Run" or "Debug" icons in the toolbar, using the project's classpath where everything is already compiled by the IDE. No need to build a war file, no need to attach to a remote JVM for debugging, no need to wait for long package/deploy/restart operations. And of course code hotswap works just like it should and makes debugging a breeze.&lt;/p&gt; 
&lt;p&gt;Now the answer "on my development machine, never" is incomplete, and should be added "on the integration server, every time a source file changes" since Hudson picks up any changes, does a full build/test cycle and deploys the new version automatically on a test machine.&lt;/p&gt; 
&lt;p&gt;Complex "enterprisey" frameworks and specifications have made us forget that things can be simple if you think a bit, and that it also often pays to do a bit of "development design" to increase the developer's productivity without resorting to "helper tools" that only add some bloat to the process.&lt;/p&gt;
</description><dc:creator xmlns:dc="http://purl.org/dc/elements/1.1/">Sylvain Wallez</dc:creator><pubDate>Tue, 11 Jan 2011 11:37:00 +0100</pubDate><guid isPermaLink="false">tag:bluxte.net,2011-01-11:musings/2011/01/11/how-often-do-you-redeploy-your-j2ee-application/</guid></item></channel></rss>