<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Charles Francoise</title>
    <description>The latest articles on Forem by Charles Francoise (@loderunner).</description>
    <link>https://forem.com/loderunner</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F715%2Fee54f486-08a3-469e-9000-fbb4a60d8df0.jpg</url>
      <title>Forem: Charles Francoise</title>
      <link>https://forem.com/loderunner</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/loderunner"/>
    <language>en</language>
    <item>
      <title>Working with forks in Go</title>
      <dc:creator>Charles Francoise</dc:creator>
      <pubDate>Tue, 09 Jan 2018 09:59:01 +0000</pubDate>
      <link>https://forem.com/loderunner/working-with-forks-in-go-3ab6</link>
      <guid>https://forem.com/loderunner/working-with-forks-in-go-3ab6</guid>
      <description>&lt;h2&gt;
  
  
  Proper use of forks
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26jp8pq23wv57p50bmbu.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2F26jp8pq23wv57p50bmbu.jpg" alt="Dinglehopper me on GitHub" width="765" height="430"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Have you ever wanted to create a fork of a Go package you're using? Maybe you need to add a feature, specific to your use case, and there is no other way than to change it inside the code. Or maybe you want to fix a bug and submit a PR to an open-source project.&lt;/p&gt;

&lt;p&gt;Whatever the case, Go, with its location-based import system, makes it hard to swap implementations of a package. If you try to just swap it into place, you'll most likely get an error along the lines of: &lt;code&gt;cannot use s (type "fork".SomeStruct) as type "original".SomeStruct in argument to SomeFunc&lt;/code&gt; as soon as you pass your data types to a function defined in another file.&lt;/p&gt;

&lt;p&gt;You can fix this with heavy refactoring — changing imports in your own code, and typecasting everything coming in from or going out to another package — but it's near impossible on a large project with many files.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/golang/proposal/blob/master/design/18130-type-alias.md" rel="noopener noreferrer"&gt;Type aliases&lt;/a&gt; can help, but with a little bit of Git magic, you can seamlessly swap a package for your fork and keep hacking away.&lt;/p&gt;

&lt;h2&gt;
  
  
  Fork and fix
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6kv3zwyfvx362042on2.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fs6kv3zwyfvx362042on2.jpg" alt="Not like that, no" width="800" height="626"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I won't go into detail on how to create a fork and submit a PR, GitHub has &lt;a href="https://guides.github.com/activities/forking/" rel="noopener noreferrer"&gt;extensive&lt;/a&gt; &lt;a href="https://help.github.com/articles/fork-a-repo/" rel="noopener noreferrer"&gt;documentation&lt;/a&gt; &lt;a href="https://help.github.com/articles/creating-a-pull-request-from-a-fork/" rel="noopener noreferrer"&gt;on the subject&lt;/a&gt;. I'll just assume you've clicked the "Fork" button on GitHub, and now have your own repository containing a duplicate of the original source.&lt;/p&gt;

&lt;p&gt;But as we've said, you can't just &lt;code&gt;go get&lt;/code&gt; the forked repository, since all the import paths will be wrong. What we want is to have your local branch, inside your &lt;code&gt;GOPATH&lt;/code&gt;, track your forked remote repository, instead of the original.&lt;/p&gt;

&lt;p&gt;Let's start by adding a remote. From the package source path, type the following:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git remote add forked &amp;lt;remote repository url&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then, let's make sure the local branch tracks the &lt;code&gt;forked&lt;/code&gt; remote, and not the &lt;code&gt;origin&lt;/code&gt; any more.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-u&lt;/span&gt; forked/master
Branch master &lt;span class="nb"&gt;set &lt;/span&gt;up to track remote branch master from forked.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;After this line, you can start committing and pushing to your own fork, and all Go packages relying on this repo will transparently use your own fork of the code.&lt;/p&gt;

&lt;p&gt;This is useful, for example, if you're sure of a bugfix, as you can start working with the fixed version of the code without waiting for the changes to be merged upstream.&lt;/p&gt;

&lt;p&gt;When you want to revert to tracking the origin, perhaps because your PR has been merged and you have deleted your fork, or because you need to use the original code for some other project, just type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;git branch &lt;span class="nt"&gt;-u&lt;/span&gt; origin/master
Branch master &lt;span class="nb"&gt;set &lt;/span&gt;up to track remote branch master from origin.

&lt;span class="c"&gt;# Reset local branch to remote HEAD&lt;/span&gt;
&lt;span class="nv"&gt;$ &lt;/span&gt;git reset &lt;span class="nt"&gt;--hard&lt;/span&gt; origin/master
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;With these few lines of git, I can quickly fork and work on an open-source Go package. It's made my collaboration on open-source projects that much easier. What is your workflow for collaborating on open-source Go projects? Do you see any mistakes or caveats? Feel free to comment below!&lt;/p&gt;

</description>
      <category>go</category>
      <category>git</category>
    </item>
    <item>
      <title>Hacking Go Interfaces</title>
      <dc:creator>Charles Francoise</dc:creator>
      <pubDate>Wed, 26 Jul 2017 12:42:30 +0000</pubDate>
      <link>https://forem.com/loderunner/hacking-go-interfaces</link>
      <guid>https://forem.com/loderunner/hacking-go-interfaces</guid>
      <description>&lt;h1&gt;
  
  
  Introduction
&lt;/h1&gt;

&lt;p&gt;Usually, in programming, interfaces precede implementation. We know what we want the pieces of our architecture to be able to do, how they'll articulate, and we only start banging out code once we're sure about this. Interfaces make it possible to reason "from the outside in", deciding the behavior of larger parts, before we break down their inner workings.&lt;/p&gt;

&lt;p&gt;But often, we're "hacking" our way "from the inside out", building some parts we know are essential first, and putting them together or wrapping them in bigger parts later. I think there's a way to show why and how to use interfaces in Go from the inside out.&lt;/p&gt;

&lt;h1&gt;
  
  
  What should we hack?
&lt;/h1&gt;

&lt;p&gt;I decided to hack a (very naive) logging framework. The idea is: everyone has an idea of what a logging framework should do, and that's kind of like having an interface (conceptually). Plus, I don't need to introduce any specific concepts that could distract us from what we're building. Finally, a logging framework is typically the kind of stuff we start hacking, wrap into some other part, and come back to later when we need to improve it.&lt;/p&gt;

&lt;p&gt;So, without any prior design, let's start banging out a logging framework in Go. I commited each chapter into a &lt;a href="https://gitlab.com/loderunner/ezlog" rel="noopener noreferrer"&gt;GitLab repository&lt;/a&gt; so you can follow the progress in the code base along with the chapters. Each chapters links to the commit at that point in the reading.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://gitlab.com/loderunner/ezlog/tree/version-1" rel="noopener noreferrer"&gt;Version 1 – Standard output&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;My very first version of the package will just have one package-level function, &lt;code&gt;Log&lt;/code&gt;, that will output messages to standard output, preceded by the time the message was logged. (Go has a pretty fun way to &lt;a href="https://golang.org/pkg/time/#pkg-constants" rel="noopener noreferrer"&gt;format time&lt;/a&gt; to a string, much easier than the old  &lt;a href="http://pubs.opengroup.org/onlinepubs/009695399/functions/strftime.html" rel="noopener noreferrer"&gt;strftime&lt;/a&gt;.)&lt;/p&gt;

&lt;p&gt;Package:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Package ezlog is a naive log implementation&lt;/span&gt;
&lt;span class="c"&gt;// used as experiment and tutorial in learning Go&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;ezlog&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"time"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="c"&gt;// Log logs a message to standard output preceded&lt;/span&gt;
&lt;span class="c"&gt;// by the time the message was emitted&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[%s] %s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 03:04:05"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Example:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="s"&gt;"gitlab.com/loderunner/ezlog"&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run examples/hello.go
[2017-07-25 06:20:55] Hello World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It's nothing fancy, but it works. We can start logging to standard output using this package now. But of course, it's not nearly enough.&lt;/p&gt;

&lt;h1&gt;
  
  
  &lt;a href="https://gitlab.com/loderunner/ezlog/tree/version-2" rel="noopener noreferrer"&gt;Version 2 – File logging&lt;/a&gt;
&lt;/h1&gt;

&lt;p&gt;The next thing we're going to log to is a file. We'll need the client of the package to give the path of a file to log to, before they start calling &lt;code&gt;Log&lt;/code&gt;. What this tells us is that our package now needs a step of &lt;em&gt;initialization&lt;/em&gt;, before it can be used. Let's add some code.&lt;/p&gt;

&lt;p&gt;We add an &lt;code&gt;Open&lt;/code&gt; function to the package that opens a file and sets it to a package variable, if successful.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;logfile&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;

&lt;span class="c"&gt;// Open opens a file to append to, creating&lt;/span&gt;
&lt;span class="c"&gt;// it if it doesn't exist&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&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;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_WRONLY&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_APPEND&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_CREATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;0644&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="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;logfile&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;f&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We then log to the file inside the &lt;code&gt;Log&lt;/code&gt; function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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="c"&gt;// Format the output string&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[%s] %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 03:04:05"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;           &lt;span class="c"&gt;// Log to stdout&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logfile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Log to a file&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We extend the test program to add the file initialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Open&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"hello.log"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Hello World!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;When we run this program, we find a new file &lt;code&gt;hello.log&lt;/code&gt; in the directory. It contains the same output as we saw in the console in the console.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ go run examples/hello.go
[2017-07-25 09:22:21] Hello World!
$ cat hello.log
[2017-07-25 09:22:21] Hello World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;"We can log to standard output and to a file and we still don't need interfaces!" Well, yes. But we're starting to see the limits of our architecture. What if we need to log to two files? What if we don't want to log to standard output? What happens if we want to log to &lt;code&gt;syslog&lt;/code&gt; or over the network? Plus, the code is starting to look a little ugly.&lt;/p&gt;

&lt;h1&gt;
  
  
  Version 3 – Loggers
&lt;/h1&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://gitlab.com/loderunner/ezlog/tree/version-3-loggers" rel="noopener noreferrer"&gt;Loggers&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;The answers to the above questions are not: add package-level variables, initialization functions, and make &lt;code&gt;Log&lt;/code&gt; a monolithic function. We want this to be modular. What we need is an arbitrary number of "loggers" that can we can configure and give to the package to do the work. Let's write two &lt;code&gt;struct&lt;/code&gt;s two encapsulate the two behaviors. One for standard output, one for files.&lt;/p&gt;

&lt;p&gt;Standard output logger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// StdoutLogger logs messages to stdout&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;StdoutLogger&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;

&lt;span class="c"&gt;// NewStdoutLogger StdoutLogger constructor&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewStdoutLogger&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;StdoutLogger&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;StdoutLogger&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Log logs the msg to stdout&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;StdoutLogger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Println&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;File logger:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// FileLogger logs messages to a file&lt;/span&gt;
&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;FileLogger&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;File&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// NewFileLogger opens a file to append to and&lt;/span&gt;
&lt;span class="c"&gt;// returns a FileLogger ready to write to the file&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewFileLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;path&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;FileLogger&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;f&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;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OpenFile&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
        &lt;span class="n"&gt;path&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_WRONLY&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_APPEND&lt;/span&gt;&lt;span class="o"&gt;|&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;O_CREATE&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="m"&gt;0644&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&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="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;FileLogger&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;},&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Log logs a message to the file&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;FileLogger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fprintln&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;f&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We've isolated the loggers, how do we put them together in the package?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&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;StdoutLogger&lt;/span&gt;
&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;FileLogger&lt;/span&gt;

&lt;span class="c"&gt;// ... omitted code here ...&lt;/span&gt;

    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;Stdout&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&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;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Log to stdout&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;File&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;File&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Log to a file&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now this just looks silly. What if we want more files? An array of &lt;code&gt;FileLogger&lt;/code&gt;s? And still no solution for other logger types that scales elegantly.&lt;/p&gt;

&lt;h2&gt;
  
  
  &lt;a href="https://gitlab.com/loderunner/ezlog/tree/version-3-interface" rel="noopener noreferrer"&gt;The interface&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;It's easy to see that the main package's &lt;code&gt;Log&lt;/code&gt; function just prepares the output, then calls &lt;code&gt;Log&lt;/code&gt; on each of the loggers. But the static typing in Go prevents us from just resolving the calls at runtime. The compiler needs to be sure that whatever we're giving it, it knows how to &lt;code&gt;Log&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;"Whatever this is, I need it to &lt;code&gt;Log&lt;/code&gt;", is &lt;em&gt;exactly&lt;/em&gt; what interfaces do in Go. When you ask for an interface type as an argument to a function, what your code is telling the compiler is: "this function takes a pointer to something, I don't care what it is, as long as it has all the methods from the interface". When returning an interface type from a function, you're saying: "don't ask what this is, all you need to know is that it does &lt;em&gt;this&lt;/em&gt;". You can imagine an interface as a contract or requirements that the underlying type needs to fulfil.&lt;/p&gt;

&lt;p&gt;Here, both of our loggers implement a &lt;code&gt;Log&lt;/code&gt; method, so we can say they have a common &lt;code&gt;interface&lt;/code&gt;. Let's hack it up.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Log&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That's it. By writing these lines, we just defined a &lt;code&gt;Logger&lt;/code&gt; interface. No need to change anything to &lt;code&gt;StdoutLogger&lt;/code&gt; and &lt;code&gt;FileLogger&lt;/code&gt;. The compiler will check if they have the &lt;code&gt;Log&lt;/code&gt; method to determine if they uphold the interface, without any indication from our part. Anyone coming from C++ or Java will know how cool this is. And if we ever extend the interface to add new methods, it will still break at compile-time if we try to use a non-conforming type, since it won't implement the new methods.&lt;/p&gt;

&lt;p&gt;We can now start using &lt;code&gt;Logger&lt;/code&gt; as a type.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;loggers&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;

&lt;span class="c"&gt;// AddLogger adds a logger to the list&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;AddLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;loggers&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nb"&gt;append&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;loggers&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="c"&gt;// Log logs a message to standard output preceded&lt;/span&gt;
&lt;span class="c"&gt;// by the time the message was emitted&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;msg&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="c"&gt;// Format the output string&lt;/span&gt;
    &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Now&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="n"&gt;output&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"[%s] %s"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"2006-01-02 03:04:05"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;msg&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Log to all loggers&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;l&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;loggers&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;l&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;output&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And that's it. It just works. By creating an interface that declares one method, that both of our loggers conform to, we can elegantly bring this all together in a few lines of code.&lt;/p&gt;

&lt;p&gt;Let's make a more complex example to see what we can do now.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Log to stdout&lt;/span&gt;
    &lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewStdoutLogger&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Tick&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// The seconds of the current time ends with 5&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;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="m"&gt;5&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="c"&gt;// Add a new file to log to&lt;/span&gt;
            &lt;span class="n"&gt;filename&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sprintf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"gopher-%s.log"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;now&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Format&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"030405"&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
            &lt;span class="n"&gt;fileLogger&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;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFileLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddLogger&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fileLogger&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="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Couldn't open new file."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;

        &lt;span class="n"&gt;ezlog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Log&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Gopher!"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This example dynamically adds loggers to a new file every 5 seconds. Here's how it works.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://asciinema.org/a/TUkN1WXIoBVie4MJoKq7zQQWC" rel="noopener noreferrer"&gt;&lt;img src="https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fl9ca84utf014ilqjzek0.png" alt="asciicast" width="800" height="519"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What next?
&lt;/h1&gt;

&lt;p&gt;Well, there's a lot to do.&lt;/p&gt;

&lt;p&gt;This framework is by no means concurrency-safe. If several goroutines call &lt;code&gt;AddLogger&lt;/code&gt; at the same time, we'll end up with a data race to the &lt;code&gt;loggers&lt;/code&gt; array and could end up losing data. Heck, it's not even concurrent itself! We could probably optimize it by using goroutines and channels for different types of loggers. We could even use Go's built-in buffered channels to implement cheap spooling of logs.&lt;/p&gt;

&lt;p&gt;There are many more loggers we might want to implement. In fact, I've already hacked together a &lt;a href="https://gitlab.com/loderunner/ezlog/blob/f3bd1f2745e9d788a7af91bf1574aee69e1599d8/net.go" rel="noopener noreferrer"&gt;network&lt;/a&gt; and a &lt;a href="https://gitlab.com/loderunner/ezlog/blob/f3bd1f2745e9d788a7af91bf1574aee69e1599d8/syslog.go" rel="noopener noreferrer"&gt;&lt;code&gt;syslog&lt;/code&gt;&lt;/a&gt; logger (which was actually a fun experience in itself that I'll talk about in another post).&lt;/p&gt;

&lt;p&gt;Here is a list of a few features I still want to add:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Leveled logs&lt;/li&gt;
&lt;li&gt;Log formatting&lt;/li&gt;
&lt;li&gt;Named loggers&lt;/li&gt;
&lt;li&gt;Concurrency &amp;amp; optimization&lt;/li&gt;
&lt;li&gt;... Removing loggers (trickier than it seems)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;In the end, this package is also a fun playground to learn Go on. I'll intend to keep fiddling with it for a while, just to see what I can do. Check out the repository to see how it's progressing. Feel free to comment, suggest ideas, or even contribute to the package.&lt;/p&gt;

</description>
      <category>go</category>
      <category>interface</category>
      <category>hacking</category>
    </item>
    <item>
      <title>Go, I love you, but you're bringing me down.</title>
      <dc:creator>Charles Francoise</dc:creator>
      <pubDate>Mon, 24 Jul 2017 16:00:39 +0000</pubDate>
      <link>https://forem.com/loderunner/go-i-love-you-but-youre-bringing-me-down</link>
      <guid>https://forem.com/loderunner/go-i-love-you-but-youre-bringing-me-down</guid>
      <description>&lt;p&gt;I've said it before, and I'll say it again: I really like Go. It's the most fun I've had learning a language since &lt;a href="https://xkcd.com/353/"&gt;Python&lt;/a&gt;. It's statically typed and compiled – and as a systems-oriented programmer, I never found anything that could really move me away from C because of this – it has a great standard library, it handles code reuse without inheritance beautifully, and those concurrency paradigms have changed my life for ever.&lt;/p&gt;

&lt;p&gt;That being said, I quickly had a few issues with some of the language's specifics. And while I've been trying to learn its patterns and conventions as best I can, I'm pretty certain that some of them could be fixed inside the language, and not by using a specific pattern or abstraction. For the sake of &lt;a href="https://dave.cheney.net/2017/06/15/simplicity-debt"&gt;simplicity&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;As I was reading Russ Cox's &lt;a href="https://blog.golang.org/toward-go2"&gt;Gophercon 2017 talk&lt;/a&gt; about Go 2, I decided to take him up on this:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;We need your help.&lt;/strong&gt;&lt;br&gt;
Today, what we need most is experience reports. Please tell us how Go is working for you, and more importantly not working for you. Write a blog post, include real examples, concrete detail, and real experience. That's how we'll start talking about what we, the Go community, might want to change about Go.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So here are, as a new Go programmer, my 2 cents about what's missing.&lt;/p&gt;

&lt;h2&gt;
  
  
  Operator overloading
&lt;/h2&gt;

&lt;p&gt;Got your attention? Good. Because I hate operator overloading. I've been through too many C++ code bases where developers thought it was better to be clever than to write a clean interface. I've had my share of over-enthusiastic coders re-defining fundamental semantics such as the dot(&lt;code&gt;.&lt;/code&gt;), arrow(&lt;code&gt;-&amp;gt;&lt;/code&gt;) or call(&lt;code&gt;()&lt;/code&gt;) operators to do very unexpected things. The cost in documentation and on-boarding new developers was huge, and the mental work of switching paradigms when coding made the whole thing quite error-prone. The fact that the stdlib does weird things pretty freely (&lt;code&gt;std::cout &amp;lt;&amp;lt; "Hello, World!"&lt;/code&gt;, anyone?) doesn't really help.&lt;/p&gt;

&lt;p&gt;But operators are also a great shorthand for some clearly defined semantics. In other words, if semantics &lt;em&gt;precede&lt;/em&gt; the operator, there's a far lesser chance to abuse them. An example would be the &lt;code&gt;[]&lt;/code&gt; operator for integer-based indexing (such as arrays or slices), or for key-value operations (such as maps). Or the usage of the &lt;code&gt;range&lt;/code&gt; keyword to iterate over arrays, slices, maps and channels.&lt;/p&gt;

&lt;p&gt;One way to make sure these semantics are well respected would be to make the operators as syntactic sugar to well-defined interfaces.&lt;/p&gt;

&lt;p&gt;Key-value operator:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="n"&gt;KeyValueMap&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
    &lt;span class="n"&gt;SetValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt;&lt;span class="p"&gt;{})&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We could then use the &lt;code&gt;[]&lt;/code&gt; operator as a shorthand to these functions.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;keyVal&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would be equivalent to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;foo&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;keyVal&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"bar"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The objects used as key would need to be hashable or comparable in some way. Perhaps the compiler could enforce the &lt;a href="https://golang.org/ref/spec#Comparison_operators"&gt;same rules&lt;/a&gt; it does with maps.&lt;/p&gt;

&lt;p&gt;Range iteration could be done similarly:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Iterator&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&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="n"&gt;Reset&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;Next&lt;/code&gt; would return the next value in the iteration, and a &lt;code&gt;bool&lt;/code&gt; that would be &lt;code&gt;true&lt;/code&gt; when the iterator is finished. &lt;code&gt;Reset&lt;/code&gt; would be used to initialize the iterator at the beginning of the &lt;code&gt;for&lt;/code&gt; loop.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&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="n"&gt;it&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;would be equivalent to&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Reset&lt;/span&gt;&lt;span class="p"&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;done&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;it&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Next&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;done&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;break&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I think this would allow Go developers to implement much more go-ish structures and I can see many cases of memory-efficient iterators that would make use of this clean syntax.&lt;/p&gt;

&lt;p&gt;Of course, this kind of breaks the strong typing in Go. Maybe a feature like this would go hand-in-hand with generics?&lt;/p&gt;

&lt;h2&gt;
  
  
  Initialization of embedded interfaces
&lt;/h2&gt;

&lt;p&gt;We recently had a case of an issue that took us a while to debug. We were using type embedding to compose different services in one structure. At first we had just one handler.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;FooHandler&lt;/span&gt; &lt;span class="k"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// some `FooHandler` methods&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
   &lt;span class="n"&gt;FooHandler&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Foo is a concrete type implementing FooHandler&lt;/span&gt;
    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;FooHandler&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;{}}&lt;/span&gt;
    &lt;span class="n"&gt;RegisterHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;h&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We embedded a second handler, but forgot to add it in the &lt;code&gt;Handler&lt;/code&gt; initialization. The error message was pretty cryptic.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;panic: runtime error: invalid memory address or nil pointer dereference
[signal SIGSEGV: segmentation violation code=0x1 addr=0x20 pc=0x10871d6]

goroutine 1 [running]:
main.RegisterHandler(0x1108140, 0x1126ac8, 0x0, 0x0)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This was fixed by adding the initialization.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="n"&gt;h&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;Handler&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;FooHandler&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Foo&lt;/span&gt;&lt;span class="p"&gt;{},&lt;/span&gt; &lt;span class="n"&gt;BarHandler&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;Bar&lt;/span&gt;&lt;span class="p"&gt;{}}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I wish the error message would have been clearer. Such a simple omission shouldn't require 30 minutes and two programmers. Maybe we're just new at Go, but I wish the error would have been more explicit. That or the compiler could warn against using zero values for embedded types. I don't know if there's a case where you would want to embed a &lt;code&gt;nil&lt;/code&gt; value. This would probably be a breaking change for a few code bases, but the benefit in memory safety could be worth it.&lt;/p&gt;

&lt;h2&gt;
  
  
  Closed channels
&lt;/h2&gt;

&lt;blockquote&gt;
&lt;p&gt;&lt;strong&gt;EDIT:&lt;/strong&gt; The issue I detailed here was only because of a feature of the language I didn't know of. It was pointed out in the comments and on &lt;a href="https://twitter.com/Sajma/status/889573024642584576"&gt;Twitter&lt;/a&gt; (and &lt;a href="https://twitter.com/Sajma/status/889589005976776704"&gt;here&lt;/a&gt;). I'll be showing Go way to avoid the problem I had.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;In the following program, the final loop loops forever while receiving zero values from both channels, &lt;code&gt;ca&lt;/code&gt; and &lt;code&gt;cb&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Create a first channel&lt;/span&gt;
    &lt;span class="n"&gt;ca&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="k"&gt;chan&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;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Send one integer over the channel every millisecond up to 9&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;10&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ca&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="c"&gt;// Create a second channel&lt;/span&gt;
    &lt;span class="n"&gt;cb&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="k"&gt;chan&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;go&lt;/span&gt; &lt;span class="k"&gt;func&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="c"&gt;// Send one integer over the channel every millisecond up to 99&lt;/span&gt;
        &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="m"&gt;100&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;
            &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Millisecond&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="nb"&gt;close&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}()&lt;/span&gt;

    &lt;span class="c"&gt;// Receive from the first available channel and loop&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a%d "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"b%d "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This problem can be fixed by reading two values from the channel. By using &lt;code&gt;n, ok := &amp;lt;-ca&lt;/code&gt;, &lt;code&gt;ok&lt;/code&gt; will be &lt;code&gt;false&lt;/code&gt; if the channel is closed. Once the channel has been closed, we set it to &lt;code&gt;nil&lt;/code&gt; as receiving from a &lt;code&gt;nil&lt;/code&gt; channel blocks.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;    &lt;span class="c"&gt;// Read from first available channel and loop&lt;/span&gt;
    &lt;span class="c"&gt;// until both channels are nil&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;ca&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="o"&gt;||&lt;/span&gt; &lt;span class="n"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;select&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;ca&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"a%d "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&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="c"&gt;// If the channel has been closed, set it to nil&lt;/span&gt;
                &lt;span class="c"&gt;// Receiving from a nil channel blocks, so we know&lt;/span&gt;
                &lt;span class="c"&gt;// this select branch will be unreachable after this&lt;/span&gt;
                &lt;span class="n"&gt;ca&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="n"&gt;n&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;cb&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;ok&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"b%d "&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;n&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="n"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;






&lt;p&gt;I'm still pretty new to Go, so I'm fairly certain these are either misconceptions on my part, or things that have been tried and abandoned because they didn't work. Feel free to give me any documentation or pointers in the comments.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Writing safer C with Clang address sanitizer</title>
      <dc:creator>Charles Francoise</dc:creator>
      <pubDate>Mon, 06 Feb 2017 15:35:17 +0000</pubDate>
      <link>https://forem.com/loderunner/writing-safer-c-with-clang-address-sanitizer</link>
      <guid>https://forem.com/loderunner/writing-safer-c-with-clang-address-sanitizer</guid>
      <description>&lt;h1&gt;
  
  
  Prologue
&lt;/h1&gt;

&lt;p&gt;We wanted to improve our password strength algorithm, and decided to go for the industry-standard &lt;a href="https://github.com/dropbox/zxcvbn" rel="noopener noreferrer"&gt;zxcvbn&lt;/a&gt;, from the people at Dropbox. Our web front-end would use the default Javascript library, and for mobile and desktop, we chose to use the &lt;a href="https://github.com/tsyrogit/zxcvbn-c" rel="noopener noreferrer"&gt;C implementation&lt;/a&gt; as it was the lowest common denominator for all platforms.&lt;/p&gt;

&lt;p&gt;Bootstrapping all of this together was done pretty fast. I had toyed around with a few &lt;a href="https://xkcd.com/936/" rel="noopener noreferrer"&gt;sample passwords&lt;/a&gt; so I decided to run it through the test suite we had for the previous password strength evaluator. The test generates a large number of random passwords according to different rules and expects the strength to be in a given range. But the test runner kept crashing with segmentation faults.&lt;/p&gt;

&lt;p&gt;It turns out the library has a lot of buffer overflow cases that are usually "harmless", but eventually crash your program when you run the evaluator function too much. I started fixing the cases I could see, but reading someone else's algorithms to track down tiny memory errors got old pretty fast. I needed a tool to help me.&lt;/p&gt;

&lt;p&gt;That's when I thought of Clang's Address Sanitizer.&lt;/p&gt;

&lt;h1&gt;
  
  
  Meet Asan
&lt;/h1&gt;

&lt;p&gt;From the &lt;a href="https://clang.llvm.org/docs/AddressSanitizer.html" rel="noopener noreferrer"&gt;Clang documentation&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;AddressSanitizer is a fast memory error detector. It consists of a compiler instrumentation module and a run-time library. The tool can detect the following types of bugs:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Out-of-bounds accesses to heap, stack and globals&lt;/li&gt;
&lt;li&gt;Use-after-free&lt;/li&gt;
&lt;li&gt;Use-after-return&lt;/li&gt;
&lt;li&gt;Use-after-scope&lt;/li&gt;
&lt;li&gt;Double-free, invalid free&lt;/li&gt;
&lt;li&gt;Memory leaks (experimental)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;That covers a large portion of the crashes I've faced in C. And its impact on performance? &lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Typical slowdown introduced by AddressSanitizer is &lt;strong&gt;2x&lt;/strong&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Perfectly acceptable in a lot of debugging contexts. Especially if it saves you hours of trying to find the proverbial needle in a corrupt stack.&lt;/p&gt;

&lt;h1&gt;
  
  
  First steps
&lt;/h1&gt;

&lt;p&gt;Let's try the sanitizer on a simple program. We'll allocate a buffer on the heap, copy each character of a string into it, and print it to standard output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="s"&gt;"Hello, World!"&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;malloc&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="k"&gt;sizeof&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;char&lt;/span&gt;&lt;span class="p"&gt;));&lt;/span&gt; &lt;span class="c1"&gt;// "Hello, World!" is 13 characters long&lt;/span&gt;

    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="mi"&gt;0&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt; &lt;span class="o"&gt;&amp;lt;&lt;/span&gt; &lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;hello&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="n"&gt;i&lt;/span&gt;&lt;span class="p"&gt;];&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="mi"&gt;13&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt; &lt;span class="o"&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;// Don't forget the terminating nul character&lt;/span&gt;

    &lt;span class="n"&gt;printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%s&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;str&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;

    &lt;span class="k"&gt;return&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If you compile and run this program, chances are it will work as predicted.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ clang -o clang-asan clang-asan.c
$ ./clang-asan
Hello, World!
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But it shouldn't. Or it should. It's &lt;a href="http://blog.regehr.org/archives/213" rel="noopener noreferrer"&gt;undefined&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;When assigning &lt;code&gt;0&lt;/code&gt; to the character at index 13, we're writing out of the array bounds, into unallocated memory. While harmless in this case, this is a classic  buffer overflow error.&lt;/p&gt;

&lt;p&gt;Let's try compiling it again with the address sanitizer.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ clang -fsanitize=address -g -o clang-asan clang-asan.c
$ ./clang-asan
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Wow. Such output. A E S T H E T I C !&lt;/p&gt;

&lt;p&gt;&lt;a href="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdbo9k8xk3828ykmsyer.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://media.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fvdbo9k8xk3828ykmsyer.jpg" alt="RAINBOW"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h1&gt;
  
  
  What happened?
&lt;/h1&gt;

&lt;p&gt;So what can we gather from that pile of hex? Let's go through it line by line.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;==36293==ERROR: AddressSanitizer: heap-buffer-overflow on address 0x60200000ef3d
at pc 0x000105960da8 bp 0x7fff5a29fa30 sp 0x7fff5a29fa28
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;AddressSanitizer found a heap buffer overflow at &lt;code&gt;0x60200000ef3d&lt;/code&gt;, a seemingly valid address (not NULL or any other clearly faulty value). The rest of the addresses are the &lt;a href="https://en.wikibooks.org/wiki/X86_Assembly/X86_Architecture" rel="noopener noreferrer"&gt;program counter, base pointer and stack pointer registers&lt;/a&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;WRITE of size 1 at 0x60200000ef3d thread T0
    #0 0x105960da7 in main clang-asan.c:10
    #1 0x7fffa6c46254 in start (libdyld.dylib+0x5254)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Write of size 1 at line 10. What's line 10?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;str[13] = 0;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We're writing outside of the heap in this instruction. And AddressSanitizer isn't having it.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0x60200000ef3d is located 0 bytes to the right of 13-byte region
[0x60200000ef30,0x60200000ef3d)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is definitely one of my favorite indications. In addition to telling which line in the code failed and where in the memory the failure happened, you get a complete description of the closest allocated region in memory (which is probably the region you were trying to access).&lt;/p&gt;

&lt;h1&gt;
  
  
  Power to the debugger
&lt;/h1&gt;

&lt;p&gt;We've seen that the address sanitizer has some pretty nifty tricks up its sleeve. The main benefit is that it will break your program on virtually any bad memory access. But its real power comes when used in conjunction with a debugger.&lt;/p&gt;

&lt;p&gt;Let's run our program again, with &lt;code&gt;lldb&lt;/code&gt; this time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ lldb -- ./clang-asan
(lldb) target create "./clang-asan"
Current executable set to './clang-asan' (x86_64)
(lldb) run
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As expected, the program crashes again, at the same line. But let's look at what we get after the usual output.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.
Process 40049 stopped
* thread #1: tid = 0x13f073, 0x00000001000e30a0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie(), queue = 'com.apple.main-thread', stop reason = Heap buffer overflow detected
    frame #0: 0x00000001000e30a0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie()
libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie:
-&amp;gt;  0x1000e30a0 &amp;lt;+0&amp;gt;: pushq  %rbp
    0x1000e30a1 &amp;lt;+1&amp;gt;: movq   %rsp, %rbp
    0x1000e30a4 &amp;lt;+4&amp;gt;: pushq  %rbx
    0x1000e30a5 &amp;lt;+5&amp;gt;: pushq  %rax
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;As we can see, the program doesn't stop on a segmentation fault in the &lt;code&gt;main()&lt;/code&gt; function, but rather in a special &lt;code&gt;__asan::AsanDie()&lt;/code&gt; function, in &lt;code&gt;libclang_rt.asan_osx_dynamic.dylib&lt;/code&gt;. Obviously, AddressSanitizer is responsible for triggering the breakpoint. What is the actual stack trace?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) bt
* thread #1: tid = 0x13f073, 0x00000001000e30a0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie(), queue = 'com.apple.main-thread', stop reason = Heap buffer overflow detected
  * frame #0: 0x00000001000e30a0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie()
    frame #1: 0x00000001000e8198 libclang_rt.asan_osx_dynamic.dylib`__sanitizer::Die() + 88
    frame #2: 0x00000001000e0a29 libclang_rt.asan_osx_dynamic.dylib`__asan::ScopedInErrorReport::~ScopedInErrorReport() + 249
    frame #3: 0x00000001000e0151 libclang_rt.asan_osx_dynamic.dylib`__asan::ReportGenericError(unsigned long, unsigned long, unsigned long, unsigned long, bool, unsigned long, unsigned int, bool) + 3953
    frame #4: 0x00000001000e11e9 libclang_rt.asan_osx_dynamic.dylib`__asan_report_store1 + 57
    frame #5: 0x0000000100000da8 clang-asan`main + 328 at clang-asan.c:10
    frame #6: 0x00007fffa6c46255 libdyld.dylib`start + 1
(lldb) frame select 5
frame #5: 0x0000000100000da8 clang-asan`main + 328 at clang-asan.c:10
   7        for (int i = 0; i &amp;lt; 13; i++) {
   8            str[i] = hello[i];
   9        }
-&amp;gt; 10       str[13] = 0;
   11
   12       printf("%s\n", str);
   13
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We can see that the &lt;code&gt;asan&lt;/code&gt; library takes over as soon we attempt to store something into memory at line 10.&lt;/p&gt;

&lt;p&gt;A couple other lines caught my attention. Let's start with:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddressSanitizer report breakpoint hit. Use 'thread info -s' to get extended information about the report.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;If we try it, we get a JSON output that nicely recaps the error, and that we can bring up if we need it again.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) thread info -s
thread #1: tid = 0x13f073, 0x00000001000e30a0 libclang_rt.asan_osx_dynamic.dylib`__asan::AsanDie(), queue = 'com.apple.main-thread', stop reason = Heap buffer overflow detected

{
  "access_size" : 1,
  "access_type" : 1,
  "address" : 105690555281181,
  "description" : "heap-buffer-overflow",
  "instrumentation_class" : "AddressSanitizer",
  "pc" : 4294970792,
  "stop_type" : "fatal_error"
}
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The other line that piqued my interest was right after we launched the program:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;AddressSanitizer debugger support is active. Memory error breakpoint has been installed and you can now use the 'memory history' command.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The documentation for the &lt;code&gt;memory history&lt;/code&gt; command is:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) help memory history
     Print recorded stack traces for allocation/deallocation events associated with an address.

Syntax: memory history &amp;lt;address&amp;gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Sounds pretty powerful, let's give it a try.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;(lldb) memory history str
  thread #4294967295: tid = 0x0001, 0x00000001000d8bf0 libclang_rt.asan_osx_dynamic.dylib`wrap_malloc + 192, name = 'Memory allocated by Thread 1'
    frame #0: 0x00000001000d8bf0 libclang_rt.asan_osx_dynamic.dylib`wrap_malloc + 192
    frame #1: 0x0000000100000c85 clang-asan`main + 37 at clang-asan.c:6
    frame #2: 0x00007fffa6c46254 libdyld.dylib`_dyld_process_info_notify_release + 44
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;We get the exact stack trace at the time this address in memory was allocated. In a more complex program, we would get the history of all the times the address was allocated and deallocated, making it a very powerful tool to understand cryptic memory bugs.&lt;/p&gt;

&lt;h1&gt;
  
  
  Putting it all to use
&lt;/h1&gt;

&lt;p&gt;Back to my practical case, how did I put the address sanitizer to good use? I simply ran the test suite, compiled with the sanitizer, with &lt;code&gt;lldb&lt;/code&gt;. Sure enough, it stopped on every line that could cause a crash. It turns out there were many cases where zxcvbn-c wrote past the end of allocated buffers, on the heap and on the stack. I fixed those cases in the C library and ran the tests again. Not a segfault in sight!&lt;/p&gt;

&lt;h1&gt;
  
  
  What next?
&lt;/h1&gt;

&lt;p&gt;I've used memory tools in the past, but they were usually unwieldy, or put such a toll on performance that they were useless in any real-life case. Clang's address sanitizer turned out to be detailed, reliable, and surprisingly easy to use. I've heard of the miracles of &lt;a href="http://valgrind.org/" rel="noopener noreferrer"&gt;Valgrind&lt;/a&gt; but macOS hardly supports it, making it a pain to use on my MacBook Pro.&lt;/p&gt;

&lt;p&gt;Coupled with Clang's &lt;a href="https://clang-analyzer.llvm.org/" rel="noopener noreferrer"&gt;static analyzer&lt;/a&gt;, AddressSanitizer is going to become a mandatory stop for evaluating code quality. It's also going to be the first tool I grab when facing confusing memory issues. There are many more case where I could use early failure and memory history to debug my code. For example, if a program crashes when accessing member of a deallocated object, we could easily trace the event that caused the deallocation, saving hours of adding and reading logs to retrace just what happened.&lt;/p&gt;

&lt;p&gt;Can you think of cases where the address sanitizer could be put to use? Cases where it would miss bugs or result in false positives? Tell me in the comments!&lt;/p&gt;

</description>
      <category>c</category>
      <category>clang</category>
      <category>memory</category>
      <category>addresssanitizer</category>
    </item>
    <item>
      <title>Hi, I'm Charles Francoise</title>
      <dc:creator>Charles Francoise</dc:creator>
      <pubDate>Mon, 12 Dec 2016 15:39:30 +0000</pubDate>
      <link>https://forem.com/loderunner/hi-im-charles-francoise</link>
      <guid>https://forem.com/loderunner/hi-im-charles-francoise</guid>
      <description>&lt;p&gt;You can find me on GitHub as &lt;a href="https://github.com/loderunner" rel="noopener noreferrer"&gt;@loderunner&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;I live in Paris.&lt;/p&gt;

&lt;p&gt;I work for &lt;a href="https://dashlane.com" rel="noopener noreferrer"&gt;Dashlane&lt;/a&gt;&lt;/p&gt;

</description>
      <category>introduction</category>
    </item>
  </channel>
</rss>
