<?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>DEV Community: Pascal Dennerly</title>
    <description>The latest articles on DEV Community by Pascal Dennerly (@dnnrly).</description>
    <link>https://dev.to/dnnrly</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%2F339179%2F7715bf92-b938-4c5a-b03e-f5658ad73c62.jpg</url>
      <title>DEV Community: Pascal Dennerly</title>
      <link>https://dev.to/dnnrly</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/dnnrly"/>
    <language>en</language>
    <item>
      <title>Quitting early for the win!</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Sat, 14 Dec 2024 01:01:16 +0000</pubDate>
      <link>https://dev.to/dnnrly/quitting-early-for-the-win-2mh1</link>
      <guid>https://dev.to/dnnrly/quitting-early-for-the-win-2mh1</guid>
      <description>&lt;p&gt;Super short summary: Exiting your program when you get an error can be a good idea. Using &lt;a href="https://github.com/dnnrly/gobail" rel="noopener noreferrer"&gt;gobail&lt;/a&gt; will make your life easier.&lt;/p&gt;

&lt;p&gt;When you get an error in your Go code, you'll normally see something like this:&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;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;myFunc&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="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Errorf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"doing my thing: %w"&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You'll notice a few things in this example:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;You have to check whether there is an error&lt;/li&gt;
&lt;li&gt;There is some text that will help diagnose the error&lt;/li&gt;
&lt;li&gt;And the error is wrapped, passed back with the text&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;So what happens next? Well it all happens again. You check the error value, describe it, pass it back. And then it all starts again.&lt;/p&gt;

&lt;p&gt;Why do we do this? Why all this effort?&lt;/p&gt;

&lt;p&gt;Well it all depends on the software that you're writing. When you get an error, you have to make a decision. What happens to that error?&lt;/p&gt;

&lt;p&gt;If you're writing an HTTP API responding to a request then eventually you're going to get to some kind of HTTP handler and you'll turn that error into some response - perhaps a little 400 with a polite reminder format their requests properly or possibly a 500 and a worrying message about the health of your application. Alternatively, if you're writing some kind of CLI tool then you might decide that the error will eventually get passed all the way back to your &lt;code&gt;main&lt;/code&gt; function. For any kind of program, you might decide that enough is enough - the program should just end because you can't do anything else.&lt;/p&gt;

&lt;p&gt;Let's look at this last option. When is it appropriate to just &lt;code&gt;exit&lt;/code&gt; your program? Here's a few reasons that I can think of:&lt;/p&gt;

&lt;p&gt;a. There's nothing else to be done, the error is so bad that everything has to stop right now&lt;br&gt;
b. There are no consequences to terminating the program (no cleanup is required, no status to respond with)&lt;br&gt;
c. Stopping early is desirable, perhaps you have a monitor that restarts the process cleanly&lt;/p&gt;

&lt;p&gt;Whatever the reason, you need to consider how you're going to exit cleanly. Now the first thing you're likely to try is this:&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;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;myFunc&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;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;"doing my thing: %v"&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="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Exit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&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;It looks pretty similar to our original error handling code but with a couple of important differences. The first is kind of obvious - there's a honking great &lt;em&gt;stop-right-g*****n-now&lt;/em&gt; statement there. Your program is not going to continue. The second point is perhaps more important. The code that is calling this sample doesn't have worry about handling any errors. There are no additional code paths that have to be tested - we can trust that that the calling code doesn't have an &lt;code&gt;if&lt;/code&gt; block to test because there's nothing returned that we have to check.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing your exits
&lt;/h2&gt;

&lt;p&gt;So I was being, perhaps, a little enthusiastic when I suggested you should just trust that your exit code is just going to work. You should probably check that the reason that you new program has stopped is for the right reason.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attempt 1 - just run your program
&lt;/h3&gt;

&lt;p&gt;This feels like it should be easy. Here's some things to consider - in the most easy case, you're just going to run your program and trigger an error condition. For example, get your CLI tool to open a file that doesn't exist. You can do this manually for a few simple cases. When the number of tests goes up, you'll probably need some kind of automation around it to help you.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Quick side note - this is probably the subject of a whole other blog post but my current favourite way of testing CLI tools uses &lt;a href="https://github.com/cucumber/godog" rel="noopener noreferrer"&gt;godog&lt;/a&gt; to write tests. It can be a little complex but I've found it supremely powerful. Here are some good examples of how I've approached it with &lt;a href="https://github.com/dnnrly/layli" rel="noopener noreferrer"&gt;layli&lt;/a&gt; and &lt;a href="https://github.com/dnnrly/wait-for" rel="noopener noreferrer"&gt;wait-for&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This approach will get you very far but sometimes it can be difficult to create the conditions that will properly exercise all of the code paths that you want to be confident about.&lt;/p&gt;

&lt;h3&gt;
  
  
  Attempt 2 - mock out the exit
&lt;/h3&gt;

&lt;p&gt;OK so now we're going to be using some of the features of the Go language. We don't actually have to call &lt;code&gt;os.Exit&lt;/code&gt; - we can call something that looks like it. So look at this:&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;ExitFunc&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;code&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;var&lt;/span&gt; &lt;span class="n"&gt;customExit&lt;/span&gt; &lt;span class="n"&gt;ExitFunc&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;Exit&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;myFunc&lt;/span&gt;&lt;span class="p"&gt;()&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;someOtherFunc&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;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;"doing my thing: %v"&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="n"&gt;customExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&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;So how are we going to take advantage of this for our testing? As the function has now been turned into a variable (&lt;code&gt;customExit&lt;/code&gt;) then we can replace the value with something else that we want to do. Like so...&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;sameAsTheAboveCode&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;TestOMGItsAllGoneWrong&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;testing&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;T&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;oldExit&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;customExit&lt;/span&gt;
    &lt;span class="k"&gt;defer&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;// Make sure we reset the exit so it can be used elsewhere&lt;/span&gt;
        &lt;span class="n"&gt;customExit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;oldExit&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="n"&gt;exitCalled&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;
    &lt;span class="n"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;
    &lt;span class="n"&gt;customExit&lt;/span&gt; &lt;span class="o"&gt;=&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;code&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="n"&gt;exitCalled&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="no"&gt;true&lt;/span&gt;
        &lt;span class="n"&gt;exitCode&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;code&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;

    &lt;span class="c"&gt;// Set up the mocks so that someOtherFunc returns an error&lt;/span&gt;

    &lt;span class="n"&gt;myFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;

    &lt;span class="c"&gt;// Assume that we're using the fantastic stretchr/testify library here&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;True&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exitCalled&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;assert&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Equal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;t&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;exitCode&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 is a much more unit-test friendly approach. You can check that the exit code used is correct - and that you actually called the exit function.&lt;/p&gt;

&lt;p&gt;On the surface, this looks great but there is one big problem - if your test passes, then you program will continue and execute the rest of the function when you expected it to exit. It will continue even though the test setup means that the rest of the execution is not valid and cause problems for your tests, such as causing panics.&lt;/p&gt;

&lt;h2&gt;
  
  
  Removing code to remove tests
&lt;/h2&gt;

&lt;p&gt;Well, this sounds a bit extreme!&lt;/p&gt;

&lt;p&gt;I feel like I should explain... Typically in "well managed" companies you need to make sure that every line of code has been proved to be working before if can be put in front of your customers. Using the above techniques you may not be able to generate the correct coverage metrics to attest that you're good. Even if it's trivial to reason about.&lt;br&gt;
All of the examples above have assumed that when we get an error then we have to check it to decide what to do (Exit with vengeance). Wouldn't it be great if we were able to exit without having to check that there was an error?&lt;/p&gt;

&lt;p&gt;Let's see what we can do.&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;checkExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&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="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;"doing my thing: %v"&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="n"&gt;customExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="p"&gt;)&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;myFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;checkExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someOtherFunc&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;Take a look at the above example. The functionality is the same but the implementation of &lt;code&gt;myFunc&lt;/code&gt; is much simpler now - there are no conditionals. We can check the implementation of the &lt;code&gt;checkExit&lt;/code&gt; function in it's own tests, meaning that whatever is new in myFunc() can be much more easily verified.&lt;/p&gt;

&lt;h2&gt;
  
  
  Introducing &lt;a href="https://github.com/dnnrly/gobail" rel="noopener noreferrer"&gt;gobail&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A new libraray, &lt;a href="https://github.com/dnnrly/gobail" rel="noopener noreferrer"&gt;gobail&lt;/a&gt; has been  created that allows you to e confident that if there is an error then it will be handled without having to add complexity to your own code. It looks like this:&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;myFunc&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;gobail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;someOtherFunc&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"with message"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;gobail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;yetAnotherFunc&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrExit&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"with message"&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 library has been fully tested, with coverage metrics, to prove it. You can safely use it without having to worry that an error will be skipped. It will also handle functions with 2 return values, like so:&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;gobail&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Return2&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;return2ValsAndError&lt;/span&gt;&lt;span class="p"&gt;())&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;OrExitMsg&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"something went wrong: %v"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Notice as well that you an include the error that is causing all of your problems.&lt;/p&gt;

&lt;p&gt;It's also possible to panic instead of exiting, printing our a stack trace and other contextual information from the program when the panic is invoked. Take a look at the &lt;a href="https://pkg.go.dev/github.com/dnnrly/gobail" rel="noopener noreferrer"&gt;docs&lt;/a&gt; for more details.&lt;/p&gt;

&lt;h2&gt;
  
  
  Isolating dependencies
&lt;/h2&gt;

&lt;p&gt;As you write software with &lt;a href="https://github.com/dnnrly/gobail" rel="noopener noreferrer"&gt;gobail&lt;/a&gt;, you will notice that you will mostly have to use it when talking to external libraries. This has the additional code that you typically need to write to handle all of the error cases can be wrapped in a call to &lt;code&gt;Return&lt;/code&gt; or &lt;code&gt;Return2&lt;/code&gt; and assume that we will exit when necessary.&lt;/p&gt;

&lt;h2&gt;
  
  
  Conclusion
&lt;/h2&gt;

&lt;p&gt;Sometimes it's desirable to exit your program instead of handling your errors in detail. The &lt;a href="https://github.com/dnnrly/gobail" rel="noopener noreferrer"&gt;gobail&lt;/a&gt; library has been created and validated so that you don't have to worry about the detail of proving this.&lt;/p&gt;

&lt;p&gt;If you find an improvement that could be made or just have a suggestion then raise a PR or an issue on the repo and the developers will get on it when they can!&lt;/p&gt;

</description>
      <category>go</category>
      <category>exit</category>
      <category>panic</category>
      <category>gobail</category>
    </item>
    <item>
      <title>Introducing Layli</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Fri, 24 Nov 2023 22:20:15 +0000</pubDate>
      <link>https://dev.to/dnnrly/introducing-layli-31mn</link>
      <guid>https://dev.to/dnnrly/introducing-layli-31mn</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;This is a story about how my simple little alternative to PlantUML came about. Please check out &lt;a href="https://github.com/dnnrly/layli"&gt;layli&lt;/a&gt; if you just want to see the end result.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;I've been an avid user of &lt;a href="https://plantuml.com"&gt;PlantUML&lt;/a&gt; for &lt;em&gt;years&lt;/em&gt;. I love the ability to define my diagrams as code. Sequence diagrams, component diagrams - just define what connects to what and you have a diagram that you can put in &lt;code&gt;git&lt;/code&gt; and render in to any image format you choose.&lt;/p&gt;

&lt;p&gt;But.&lt;/p&gt;

&lt;p&gt;BUT....&lt;/p&gt;

&lt;p&gt;...very quickly, you find that your component diagrams end up looking a bit messy. So you use &lt;code&gt;linetype ortho&lt;/code&gt; to get the straight lines with corners, rather than curves. Then you have to arrange the boxes around the page and you add hidden connections (&lt;code&gt;-[hidden]-&amp;gt;&lt;/code&gt; and play with the line lengths (using &lt;code&gt;--&amp;gt;&lt;/code&gt; and &lt;code&gt;---&amp;gt;&lt;/code&gt;, perhaps even &lt;code&gt;----&amp;gt;&lt;/code&gt;). All of a sudden you discover that your simple diagram becomes a mess of crossing lines and kludges to separate the nodes so that it looks pretty.&lt;/p&gt;

&lt;p&gt;So what to do? I love the ability to specify my diagrams as code. This works really nicely for sequence diagrams but my experience with component diagrams is often...disappointing.&lt;/p&gt;

&lt;h2&gt;
  
  
  A manifesto
&lt;/h2&gt;

&lt;p&gt;I was frustrated with what I was working on and had a couple of insights. Surely there should be some simple guidelines that guarantee pretty diagrams? So I made some notes and eventually came up with this list or rules:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Edge paths must travel across a "path grid"&lt;/li&gt;
&lt;li&gt;Node borders must be on the "path grid"&lt;/li&gt;
&lt;li&gt;Edges must meet nodes at "ports"&lt;/li&gt;
&lt;li&gt;Ports must sit on the "path grid"&lt;/li&gt;
&lt;li&gt;Where a port is not specified, layli may select a "default" port on any side of the node&lt;/li&gt;
&lt;li&gt;Nodes must be layed out so that the total area marked by the outside bounds of every node is as small as possible&lt;/li&gt;
&lt;li&gt;Nodes must be seperated by at least 1 space on the "path grid"&lt;/li&gt;
&lt;li&gt;Edges must must not cross!&lt;/li&gt;
&lt;li&gt;Edges must follow a grid path (ie. not curved or diagonal)&lt;/li&gt;
&lt;li&gt;Edges must be as short as possible&lt;/li&gt;
&lt;li&gt;Edges must have as few corners as possible&lt;/li&gt;
&lt;li&gt;Edge paths may sit on top of each other at the beginning or at the end&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I think this is a reasonable start. It almost looks like a manifesto!&lt;/p&gt;

&lt;h2&gt;
  
  
  Getting started on Layli
&lt;/h2&gt;

&lt;p&gt;After a little time prevaricating, I set out to clobber the keyboard a little and Layli slowly came in to being. The first thing I had to do was figure out how to arrange the boxes on my diagram (the nodes). I decided that the simplest way to do this was to just implement a primitive flow layout - just arrange them in to a square arrangement, row by column.&lt;/p&gt;

&lt;p&gt;Next up, I had to draw connections between the nodes (edges). To do this, I looked back to an blog that I read a couple years ago that described using &lt;a href="https://en.wikipedia.org/wiki/Dijkstra%27s_algorithm"&gt;Dijkstra's shortest path algorithm&lt;/a&gt; to plot paths between nodes. I forget the details but this seemed to be an intriguing approach. After a little work, I had something that looked pretty decent:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://github.com/dnnrly/layli#an-example-diagram"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SLapgexK--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/29j1mfiu5kk4gad92qvu.png" alt="Nodes laid out on a grid with connections between them" width="720" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;After a little more work, I was able to implement some more features. A handful of different node arrangements alongside trying to shuffle the order that we draw paths so we don't get crossing lines.&lt;/p&gt;

&lt;p&gt;There're more examples &lt;a href="https://github.com/dnnrly/layli/blob/master/examples/README.md"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  What next
&lt;/h2&gt;

&lt;p&gt;I've got a few items on my &lt;a href="https://github.com/dnnrly/layli/issues"&gt;TODO list&lt;/a&gt;. Allowing you to specify nodes absolutely - giving them coordinates on your diagram, adding some styling, making the path-finding algorithm prettier. Who know's?&lt;/p&gt;

&lt;p&gt;Maybe this is something that you'd like to contribute to? Just &lt;a href="https://github.com/dnnrly/layli/issues/new/choose"&gt;raise an issue&lt;/a&gt; or a pull request and I'd be happy to take a look!&lt;/p&gt;

&lt;p&gt;Download &lt;a href="https://github.com/dnnrly/layli"&gt;layli&lt;/a&gt; and start using it now!&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>What will make me happy, as a #hacktoberfest maintainer</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Mon, 05 Oct 2020 20:54:21 +0000</pubDate>
      <link>https://dev.to/dnnrly/what-will-make-me-happy-as-a-hacktoberfest-maintainer-39f8</link>
      <guid>https://dev.to/dnnrly/what-will-make-me-happy-as-a-hacktoberfest-maintainer-39f8</guid>
      <description>&lt;blockquote&gt;
&lt;p&gt;The original version of this appeared as a tweet thread a few days ago:&lt;br&gt;
&lt;a href="https://twitter.com/pascaldoesgo/status/1311799941791133697?s=19"&gt;https://twitter.com/pascaldoesgo/status/1311799941791133697?s=19&lt;/a&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h1&gt;
  
  
  Hey #hacktoberfest beginners!
&lt;/h1&gt;

&lt;p&gt;I'm a very small scale maintainer and here are some things that you could do that I, personally, would value greatly! I suspect most maintainers would too. I personally look after 3 open source projects, essentially written to solve problems.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Shameless plug, here they are:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;&lt;a href="https://github.com/dnnrly/abbreviate"&gt;abbreviate&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dnnrly/httpref"&gt;httpref&lt;/a&gt;&lt;/li&gt;
&lt;li&gt;&lt;a href="https://github.com/dnnrly/s3backup"&gt;s3backup&lt;/a&gt;&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As you can see, it's not much but it's mine.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;h2&gt;
  
  
  Deciding on a contribution
&lt;/h2&gt;

&lt;p&gt;First of all, I'd probably take a look at open issues on a project. A lot of projects will tag them with labels like &lt;code&gt;help wanted&lt;/code&gt; or &lt;code&gt;beginners&lt;/code&gt;. You can see quite quickly whether a project might have something they think is a good starting point for you. If you have an idea of what you could do to implement the change then just ask on the issue. I would happily spend a little time on feedback.&lt;/p&gt;

&lt;p&gt;If you think you have an idea for an entirely new change that doesn't already exist then raise your own issue to discuss it first. This has been called "talk first" or &lt;a href="https://dave.cheney.net/2019/02/18/talk-then-code"&gt;talk then code&lt;/a&gt; development. It'll help me understand what's coming in. And help me to give you some guidance.&lt;/p&gt;

&lt;h2&gt;
  
  
  What changes can you make?
&lt;/h2&gt;

&lt;p&gt;4 1-line puntuation changes in separate PRs is  no help to anyone. I've had at 3 pull requests of this type already, including changes to the code of conduct and project license. The changes accidentally changed the legal meaning of the license text, moving it away from being the kind of project I want it to be. This is &lt;strong&gt;not&lt;/strong&gt; cool!&lt;/p&gt;

&lt;p&gt;Honest grammar and punctuation fixes are valued! If you've spent some time reviewing a README and you think you can make it better, then THANK YOU! I am a human and I old enough and had my ego punctured enough to realise that I make mistakes. All the time! If you spot something that you think isn't quite right the raise that PR.&lt;/p&gt;

&lt;p&gt;Adding and improving documentation is the best contribution! It's the bit most developers struggle with. Usage guides, installation instructions, FAQs. These are great candidates for documentation changes that always seem to need more work. Certainly for me, if I'm intimately familiar with a tool or some code then I find it harder to understand what it takes to start using it. An outside perspective is actually a great asset for this kind of contribution.&lt;/p&gt;

&lt;h2&gt;
  
  
  Making that change
&lt;/h2&gt;

&lt;p&gt;Now this section is more about my personal style of contributing. It's an approach when extending my own projects as well as at work.&lt;/p&gt;

&lt;p&gt;First off open a draft PR early, fill out the PR template, make me aware of what you're doing. This achieves a few things all in one go.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Let's you use the CI/CD tooling where it's available. This depends very much on what the project is using to do their testing and deploying. It probably won't work for Github actions but might for Travis or CircleCI etc.&lt;/li&gt;
&lt;li&gt;Makes me aware of an incoming change.&lt;/li&gt;
&lt;li&gt;Gives me an opportunity to give you some early feedback for larger changes&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;I'm happy to review your code and help steer you if you don't feel confident or feel you just need some advice.&lt;/p&gt;

&lt;p&gt;You don't have to be a confident developer to start coding. I remember my first attempts at code. I didn't know what I was doing for a long time. To be fair, I still make it up a little now. 😅&lt;/p&gt;

&lt;h1&gt;
  
  
  What you can expect from me
&lt;/h1&gt;

&lt;p&gt;Be mindful that I have a full time job, small kids, a wife, people that call me on the phone, DIY, a laptop that we share amongst us.&lt;/p&gt;

&lt;p&gt;I'll try to help you as much as I can but I can't promise to be totally on it all the time.&lt;/p&gt;

&lt;p&gt;I &lt;em&gt;will&lt;/em&gt; take a look at all changes that come in a few days! If you've spent the time to raise a pull request then I owe it to you to give it the proper amount of attention.&lt;/p&gt;

&lt;h2&gt;
  
  
  What I want you to get something from #hacktoberfest
&lt;/h2&gt;

&lt;p&gt;Most importantly, have fun!&lt;/p&gt;

&lt;p&gt;I mean a free T-Shirt is all very nice but I want you to enjoy what you're doing. You'll be more engaged and find it easier to contribute.&lt;/p&gt;

&lt;p&gt;Ultimately #hacktoberfest is about building the Open Source community and joining in makes you a part of that.&lt;/p&gt;

</description>
      <category>hacktoberfest</category>
      <category>contributorswanted</category>
    </item>
    <item>
      <title>Introducing Abbreviationist</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Tue, 29 Sep 2020 22:19:38 +0000</pubDate>
      <link>https://dev.to/dnnrly/introducing-abbreviationist-1lfm</link>
      <guid>https://dev.to/dnnrly/introducing-abbreviationist-1lfm</guid>
      <description>&lt;p&gt;Just a bit of blatant self promotion here. I've been playing with my little CLI tool &lt;a href="https://github.com/dnnrly/abbreviate"&gt;abbreviate&lt;/a&gt; and wondering what I could do next. I also need to practice my very new front-end skills so I put together this site to meld the 2 things:&lt;/p&gt;

&lt;p&gt;&lt;a href="https://abbreviationist.herokuapp.com/"&gt;https://abbreviationist.herokuapp.com/&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It's not much but after so many years hiding in the backend, putting up a simple site with my own HTML and CSS is a big deal for me.&lt;/p&gt;

&lt;p&gt;If you have any comments or feedback then feel free to let me know. :)&lt;/p&gt;

</description>
      <category>go</category>
      <category>sideprojects</category>
    </item>
    <item>
      <title>Fun Coding</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Sat, 28 Mar 2020 21:15:09 +0000</pubDate>
      <link>https://dev.to/dnnrly/fun-coding-4a8n</link>
      <guid>https://dev.to/dnnrly/fun-coding-4a8n</guid>
      <description>&lt;p&gt;Fun Coding&lt;br&gt;
/verb/&lt;/p&gt;

&lt;p&gt;To develop code for ones own pleasure. This may or may not be related to your day job. Perhaps a side project, perhaps not. The principle is that it's for fun.&lt;/p&gt;

</description>
      <category>programming</category>
      <category>life</category>
    </item>
    <item>
      <title>Rewarding Github contributions</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Tue, 10 Mar 2020 21:00:43 +0000</pubDate>
      <link>https://dev.to/dnnrly/rewarding-github-contributions-1pl4</link>
      <guid>https://dev.to/dnnrly/rewarding-github-contributions-1pl4</guid>
      <description>&lt;p&gt;So I'll probably be cross posting on Twitter or something but here goes...&lt;/p&gt;

&lt;p&gt;How do you reward people that take the time to contribute?&lt;/p&gt;

&lt;p&gt;I recently had someone fix a bug in &lt;a href="https://github.com/dnnrly/httpref"&gt;httpref&lt;/a&gt;. No prompting, just a PR out of the blue that nailed the problem. I was shocked, and surprised, and so so glad that someone had taken the time.&lt;/p&gt;

&lt;p&gt;Apart from a cursory 'thanks' when I hit merge and an impromptu shout out on Twitter I couldn't really do anything.&lt;/p&gt;

&lt;p&gt;Is this something that anyone has been able to do? Just show someone how much you appreciate what they've done?&lt;/p&gt;

&lt;p&gt;Discuss...&lt;/p&gt;

</description>
      <category>github</category>
      <category>community</category>
      <category>opensource</category>
      <category>discuss</category>
    </item>
    <item>
      <title>Learning Frontend as a Backend dev</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Thu, 27 Feb 2020 22:10:47 +0000</pubDate>
      <link>https://dev.to/dnnrly/learning-frontend-as-a-backend-dev-4hh5</link>
      <guid>https://dev.to/dnnrly/learning-frontend-as-a-backend-dev-4hh5</guid>
      <description>&lt;p&gt;Hey all, I thought I'd pull the community for tips on learning Frontend development.&lt;/p&gt;

&lt;p&gt;I've been writing backend software in various forms for many, many years now. Even so, Frontwnd feels magical and scary.&lt;/p&gt;

&lt;p&gt;It's definitely a skill I'm missing, but I wouldn't know where to start now.&lt;/p&gt;

&lt;p&gt;Has anyone done this particular journey? Any tips?&lt;/p&gt;

</description>
      <category>discuss</category>
      <category>react</category>
      <category>javascript</category>
      <category>vue</category>
    </item>
    <item>
      <title>THIS_IS_A_CONSTANT</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Thu, 27 Feb 2020 20:18:13 +0000</pubDate>
      <link>https://dev.to/dnnrly/thisisaconstant-3e2o</link>
      <guid>https://dev.to/dnnrly/thisisaconstant-3e2o</guid>
      <description>&lt;p&gt;A junior engineer asked a great question while we were pairing&lt;/p&gt;

&lt;p&gt;"Why does this variable have to be in upper case?"&lt;/p&gt;

&lt;p&gt;Well, because it's static final, of course.&lt;/p&gt;

&lt;p&gt;But why?&lt;/p&gt;

&lt;p&gt;So I had to think about this one and wondered why myself. What's so different? And why did people decide this was a good idea?&lt;/p&gt;

&lt;p&gt;So the obvious difference is that because it's final, it can't be modified after it has been initialised. And it's static, meaning that it's a property of the class and not of this instance.&lt;/p&gt;

&lt;p&gt;It's as close as you really get, in Java, to a const in other languages.&lt;/p&gt;

&lt;p&gt;But, he asked, why does that mean we have to make it upper case with underscores? Won't the compiler tell us when you try to change it?&lt;/p&gt;

&lt;p&gt;Well it's a convention that we used to tell us that we need to use this field differently, like we used to back in the old C days, and it's stuck from there.&lt;/p&gt;

&lt;p&gt;But what was so different about C?&lt;/p&gt;

&lt;p&gt;So there wasn't really the concept of a immutables for a while in C either. BUT we did have the #define directive. This told the compiler that the next thing it saw on the line would be a symbol that would be replaced exactly with the thing after that.&lt;/p&gt;

&lt;p&gt;So you would see something like:&lt;br&gt;
&lt;code&gt;#define STR "my string"&lt;/code&gt;&lt;/p&gt;

&lt;p&gt;When the compiler saw STR, it would literally replace that symbol with "my string" when it was processing that file.&lt;/p&gt;

&lt;p&gt;It was important to know that you were dealing with something special, something that could break in REALLY weird ways! Anyone remember the old "end of file when ';' expected - but it's  RIGHT THERE!"?&lt;/p&gt;

&lt;p&gt;So here we are in 2020, writing Java variables with different case because it looks like a constant, because we have to know to treat it differently, almost with reverence, because of lessons learned in another language.&lt;/p&gt;

</description>
      <category>c</category>
      <category>java</category>
      <category>history</category>
    </item>
    <item>
      <title>Same post at the top of my feed</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Thu, 20 Feb 2020 23:51:55 +0000</pubDate>
      <link>https://dev.to/dnnrly/same-post-at-the-top-of-my-feed-3gin</link>
      <guid>https://dev.to/dnnrly/same-post-at-the-top-of-my-feed-3gin</guid>
      <description>&lt;p&gt;Hey,&lt;/p&gt;

&lt;p&gt;I signed up tonight and clicked on a post to see what it's about. But now that article, as important and insightful as it is, appears at the top of my feed and I can't figure out how to remove it.&lt;/p&gt;

&lt;p&gt;Any suggestions?&lt;/p&gt;

</description>
      <category>help</category>
    </item>
    <item>
      <title>Testing Go CLI Tools</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Wed, 12 Feb 2020 21:08:19 +0000</pubDate>
      <link>https://dev.to/dnnrly/testing-go-cli-tools-4eic</link>
      <guid>https://dev.to/dnnrly/testing-go-cli-tools-4eic</guid>
      <description>&lt;h1&gt;
  
  
  Testing Go CLI Tools (part 1)
&lt;/h1&gt;

&lt;p&gt;This has all started from a very simple tweet from &lt;a href="https://twitter.com/matryer"&gt;Mat Ryer&lt;/a&gt;&lt;/p&gt;


&lt;blockquote class="twitter-tweet"&gt;
&lt;p&gt;I don’t use func main In &lt;a href="https://twitter.com/hashtag/golang?src=hash&amp;amp;ref_src=twsrc%5Etfw"&gt;#golang&lt;/a&gt; 😂&lt;br&gt;&lt;br&gt;But seriously, I always make a new little “run” function and then immediately call that, passing in args and io.Writer for stdout etc.&lt;br&gt;&lt;br&gt;It’s the easiest way I’ve found to make func main testable. &lt;a href="https://t.co/8BQ0EEmU5x"&gt;&lt;/a&gt;&lt;a href="https://t.co/8BQ0EEmU5x"&gt;https://t.co/8BQ0EEmU5x&lt;/a&gt;&lt;/p&gt;— mat_ryer.go (@matryer) &lt;a href="https://twitter.com/matryer/status/1227609908394287104?ref_src=twsrc%5Etfw"&gt;February 12, 2020&lt;/a&gt;
&lt;/blockquote&gt;  

&lt;p&gt;What is going on?&lt;/p&gt;

&lt;h2&gt;
  
  
  Interlude in to my testing journey
&lt;/h2&gt;

&lt;p&gt;So I have a confession to make - I like testing my code. I read about it first in &lt;a href="https://www.joelonsoftware.com/"&gt;Joel Spolsky’s&lt;/a&gt; book “Joel on Software”. Unit testing was a thing that I did a little 20 years ago when I was writing C for mobile phones and then C++ for Windows applications (before there were Apps). There was no common unit testing framework that people always looked to, we just cobbled it together with what we had.&lt;/p&gt;

&lt;p&gt;Then I moved to a company that did C# and discovered that there WERE frameworks for you to use. In this case, NUnit. Well, that was a revelation. Everything was tested, every code path and every combination of &lt;code&gt;if&lt;/code&gt; statement. It was great to feel like your code &lt;em&gt;worked&lt;/em&gt;!&lt;/p&gt;

&lt;p&gt;Lets move forward a few years. Unit testing again in C++ with CPPUnit, meeting actual people whose full time job it was to test your software. I even learned some of the theory behind testing, passing a proper QA certification - &lt;a href="https://www.istqb.org/"&gt;ISTQB&lt;/a&gt;. Only the basic one mind, but it was a start. TDD became a thing that I tried and failed to do. Testing still involved all the code paths.&lt;/p&gt;

&lt;p&gt;So now we arrive at the present day. I’ve become less bad. I do TDD before I’ve even created the file that the Production code will go in. I test behaviours and not implementation. Occasionally I even make it so I can refactor my code without needing to change the tests. I’m not so worried about getting all of the code paths checked multiple times but I still care when there are gaps.&lt;/p&gt;

&lt;h2&gt;
  
  
  Testing CLI tools
&lt;/h2&gt;

&lt;p&gt;It’s actually quite hard to test everything in a command line tool. When you think about it, how is a Unit Testing framework going to help you to parse command line arguments? What happens when some of the output goes to STDOUT? What about STDERR? And how do we get any kind of code coverage statistics?&lt;/p&gt;

&lt;h3&gt;
  
  
  BATS
&lt;/h3&gt;

&lt;p&gt;My first attempt at solving this uses a great framework called &lt;a href="https://github.com/bats-core/bats-core"&gt;BATS&lt;/a&gt;. This is essentially a Bash based Unit Testing framework. You can use this to to make calls to you CLI tool and validate the output. You can see how I’ve done this in a couple of places:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;a href="https://github.com/dnnrly/goclitem/blob/e9956a375c37de70a7874b7d78dfddc5c7ceea09/test/basic.bats"&gt;goclitem&lt;/a&gt;: a simple, opinionated, Go CLI application template&lt;/li&gt;
&lt;li&gt;
&lt;a href="https://github.com/dnnrly/abbreviate/blob/a706c0471455f3b0908896f46a2f6991fa73bcb8/acceptance.bats"&gt;abbreviate&lt;/a&gt;: a tool for abbreviating long strings (it’s a pre-cursor to &lt;code&gt;goclitem&lt;/code&gt;, which is why the structure is a little different)&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Here we can see that I’m building the tool and then actually invoking it, testing my expectations against the real fully built tool. It’s great. BUT…&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;We can’t check the code coverage&lt;/li&gt;
&lt;li&gt;We can’t use the nice testing tools that Go and 3rd party packages provide&lt;/li&gt;
&lt;/ul&gt;

&lt;h3&gt;
  
  
  Calling &lt;code&gt;main()&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;This was the next obvious approach. This didn’t work that well. There was none of the control offered by the regular unit tests but there was difficulty intercepting the output.&lt;/p&gt;

&lt;h3&gt;
  
  
  Using &lt;code&gt;run&lt;/code&gt;
&lt;/h3&gt;

&lt;p&gt;Now we get on to Matt Ryer’s comment. What is it trying to do? Essentially this allows us to have an entry point to the CLI without having be locked in to &lt;code&gt;main&lt;/code&gt;. In part 2, I’ll dig in to how this is used.&lt;/p&gt;

</description>
      <category>go</category>
      <category>testing</category>
      <category>cli</category>
    </item>
    <item>
      <title>Go Interface Generation</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Fri, 26 Oct 2018 21:58:35 +0000</pubDate>
      <link>https://dev.to/dnnrly/go-interface-generation-34gg</link>
      <guid>https://dev.to/dnnrly/go-interface-generation-34gg</guid>
      <description>&lt;h1&gt;
  
  
  Go Interface Generation
&lt;/h1&gt;

&lt;p&gt;I’d like to rave about a tool that I discovered recently. But first…a little history.&lt;/p&gt;

&lt;p&gt;I’ve been working with &lt;a href="https://github.com/gobuffalo/buffalo"&gt;Buffalo&lt;/a&gt; and enjoying it very much. It’s all there in front of you, in Go (my very favourite language) and it’s easy to take your service from the basic out-of-the-box template to adding your own domain models and business logic.&lt;/p&gt;

&lt;p&gt;But I also have a background in Java of the Big Business kind. We’re talking full &lt;a href="https://en.wikipedia.org/wiki/Domain-driven_design"&gt;DDD&lt;/a&gt; and &lt;a href="https://www.techopedia.com/definition/24306/three-tier-application"&gt;3-tier applications&lt;/a&gt; in web containers, JCA components and fancy messaging solutions.&lt;/p&gt;

&lt;p&gt;Now the thing I like about 3-tier applications is the strong seperation of concerns. Buffalo, as easy as it is, doesn’t have this same seperation. Buffalo deals with this by making strong use of integration tests using a full database implementation and utilities to manage database schemas and populating the database with data according to what is defined in your text fixtures.&lt;/p&gt;

&lt;p&gt;In short, I want to be able to take the business logic out of the handler and put it in a repository that I can abstract away so that when I do my testing (first), I can make sure that I’m only testing 1 thing at a time.&lt;/p&gt;

&lt;h2&gt;
  
  
  How do we achieve this in Buffalo?
&lt;/h2&gt;

&lt;p&gt;Well the obvious way is to move the logic for making queries against the database in to its own type, passing in the dependencies as members of this class. Stub out the dependencies - a route for validating outputs against the inputs that we insert.&lt;/p&gt;

&lt;p&gt;Buffalo makes extensive use of the incredibly useful package &lt;a href="https://github.com/gobuffalo/pop"&gt;Pop&lt;/a&gt;. Unfortunately, access to the database in this package is via the &lt;a href="https://godoc.org/github.com/gobuffalo/pop#Connection"&gt;Connection&lt;/a&gt; type. It’s unfortunate because it is a &lt;code&gt;struct&lt;/code&gt;, which means that we can’t just insert a mock version of it in to the units that we’d like to test.&lt;/p&gt;

&lt;p&gt;To perform this injection of a mock, we need to create an interface that exposes each of the exported functions on the &lt;code&gt;Connection&lt;/code&gt; type.&lt;/p&gt;

&lt;p&gt;After a little searching, I found &lt;a href="//github.com/vburenin/ifacemaker"&gt;&lt;code&gt;ifacemaker&lt;/code&gt;&lt;/a&gt;. This tools reads the struct and creates an interface that allows access to each of the exported functions on that type.&lt;/p&gt;

&lt;p&gt;To run the tool, I did this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;ifacemaker --file ~/go/src/github.com/gobuffalo/pop/connection.go --struct Connection --iface DBConnection --pkg repo

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;This presented the following type:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight mosel"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;

&lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;DBConnection&lt;/span&gt; &lt;span class="p"&gt;...&lt;/span&gt;
&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DBConnection&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
        &lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;MigrationURL&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;migrations&lt;/span&gt;
        &lt;span class="n"&gt;MigrationURL&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;MigrationTableName&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="n"&gt;migrations&lt;/span&gt;
        &lt;span class="n"&gt;MigrationTableName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&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;error&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Close&lt;/span&gt; &lt;span class="n"&gt;destroys&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
        &lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Transaction&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;connection&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;the&lt;/span&gt; &lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;rolled&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otherwise&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;automatically&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;NewTransaction&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
        &lt;span class="n"&gt;NewTransaction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(*&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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;Rollback&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;automatically&lt;/span&gt; &lt;span class="n"&gt;rollback&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regardless&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
        &lt;span class="n"&gt;Rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="s2"&gt;"empty"&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
        &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;
        &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;TruncateAll&lt;/span&gt; &lt;span class="n"&gt;truncates&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt;
        &lt;span class="n"&gt;TruncateAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;We can now use this in our Go mocking tools - for example &lt;a href="https://github.com/stretchr/testify/"&gt;&lt;code&gt;github.com/stretchr/testify/mock&lt;/code&gt;&lt;/a&gt;. But if we’re going to use a mock, we have to generate one. Here’s where we turn to &lt;a href="https://github.com/vektra/mockery/"&gt;mockery&lt;/a&gt;. The first time you use it - it’ll fail. This is because it doesn’t populate the package imports and package names (for example, &lt;code&gt;Connection&lt;/code&gt; rather than &lt;code&gt;pop.Connection&lt;/code&gt;). Fortunately this is easy to fix, giving this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight mosel"&gt;&lt;code&gt;&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;repo&lt;/span&gt;

&lt;span class="n"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s2"&gt;"github.com/gobuffalo/pop"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;DBConnection&lt;/span&gt; &lt;span class="n"&gt;represents&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;Buffalo&lt;/span&gt; &lt;span class="n"&gt;pop&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;database&lt;/span&gt;
&lt;span class="n"&gt;type&lt;/span&gt; &lt;span class="n"&gt;DBConnection&lt;/span&gt; &lt;span class="n"&gt;interface&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;String&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;URL&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
    &lt;span class="n"&gt;URL&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;MigrationURL&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt; &lt;span class="n"&gt;used&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;running&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;migrations&lt;/span&gt;
    &lt;span class="n"&gt;MigrationURL&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;MigrationTableName&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;name&lt;/span&gt; &lt;span class="k"&gt;of&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;table&lt;/span&gt; &lt;span class="k"&gt;to&lt;/span&gt; &lt;span class="n"&gt;track&lt;/span&gt; &lt;span class="n"&gt;migrations&lt;/span&gt;
    &lt;span class="n"&gt;MigrationTableName&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="k"&gt;string&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Open&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&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;error&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Close&lt;/span&gt; &lt;span class="n"&gt;destroys&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;active&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;Close&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Transaction&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;start&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;connection&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;the&lt;/span&gt; &lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt; &lt;span class="n"&gt;an&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt; &lt;span class="k"&gt;then&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;rolled&lt;/span&gt; &lt;span class="n"&gt;back&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;otherwise&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;automatically&lt;/span&gt; &lt;span class="n"&gt;commit&lt;/span&gt; &lt;span class="n"&gt;at&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="k"&gt;end&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Transaction&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;NewTransaction&lt;/span&gt; &lt;span class="n"&gt;starts&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="n"&gt;on&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;
    &lt;span class="n"&gt;NewTransaction&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;(*&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&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;Rollback&lt;/span&gt; &lt;span class="n"&gt;will&lt;/span&gt; &lt;span class="n"&gt;open&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt; &lt;span class="k"&gt;and&lt;/span&gt; &lt;span class="n"&gt;automatically&lt;/span&gt; &lt;span class="n"&gt;rollback&lt;/span&gt; &lt;span class="n"&gt;that&lt;/span&gt; &lt;span class="n"&gt;transaction&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;when&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;inner&lt;/span&gt; &lt;span class="k"&gt;function&lt;/span&gt; &lt;span class="n"&gt;returns&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;regardless&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt; &lt;span class="n"&gt;This&lt;/span&gt; &lt;span class="n"&gt;can&lt;/span&gt; &lt;span class="n"&gt;be&lt;/span&gt; &lt;span class="n"&gt;useful&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;tests&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;etc&lt;/span&gt;&lt;span class="p"&gt;...&lt;/span&gt;
    &lt;span class="n"&gt;Rollback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;fn&lt;/span&gt; &lt;span class="n"&gt;func&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;tx&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Connection&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;Q&lt;/span&gt; &lt;span class="n"&gt;creates&lt;/span&gt; &lt;span class="n"&gt;a&lt;/span&gt; &lt;span class="n"&gt;new&lt;/span&gt; &lt;span class="s2"&gt;"empty"&lt;/span&gt; &lt;span class="n"&gt;query&lt;/span&gt; &lt;span class="n"&gt;for&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;current&lt;/span&gt; &lt;span class="n"&gt;connection&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;
    &lt;span class="n"&gt;Q&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;*&lt;/span&gt;&lt;span class="n"&gt;pop&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Query&lt;/span&gt;
    &lt;span class="p"&gt;//&lt;/span&gt; &lt;span class="n"&gt;TruncateAll&lt;/span&gt; &lt;span class="n"&gt;truncates&lt;/span&gt; &lt;span class="n"&gt;all&lt;/span&gt; &lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="k"&gt;from&lt;/span&gt; &lt;span class="n"&gt;the&lt;/span&gt; &lt;span class="n"&gt;datasource&lt;/span&gt;
    &lt;span class="n"&gt;TruncateAll&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="n"&gt;error&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;The next time we run &lt;code&gt;mockery&lt;/code&gt;, it magically works. Take a look at this snippet, if it compiles then you have yourself an interface over a &lt;code&gt;struct&lt;/code&gt; to unlock your unit tests.&lt;/p&gt;

&lt;p&gt;The following code &lt;em&gt;should&lt;/em&gt; work, although you may need to fill in the blanks:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;
func AcceptConnection(tx DBConnection) {}

func TestMocks(t *testing.T) {
    tx := &amp;amp;pop.Connection{}
    mx := &amp;amp;mocks.DBConnection{}

    AcceptConnection(tx)
    AcceptConnection(mx)
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;If you get this far then you have all of the components needed to add a testable repository tier in your Buffalo app.&lt;/p&gt;

</description>
      <category>go</category>
      <category>buffalo</category>
      <category>domaindrivendesign</category>
    </item>
    <item>
      <title>Semaphores and Threadpools in Go</title>
      <dc:creator>Pascal Dennerly</dc:creator>
      <pubDate>Wed, 03 Oct 2018 20:43:56 +0000</pubDate>
      <link>https://dev.to/dnnrly/semaphores-and-threadpools-in-go-4h93</link>
      <guid>https://dev.to/dnnrly/semaphores-and-threadpools-in-go-4h93</guid>
      <description>&lt;h1&gt;
  
  
  Semaphores and Threadpools in Go
&lt;/h1&gt;

&lt;p&gt;Here’s a thing I was thinking about today. I had to make a load of REST calls to an API. The first one was a query to return matching objects and then for each result, make another to get more details. Version one made each request one after the other and it was &lt;em&gt;slow&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;Let’s look at some code to show what’s going on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;package main

import (
    "log"
    "time"
)

func main() {
    start := time.Now()

    // Imagine this is the result of a search on a REST API
    results := []int{10, 15, 8, 3, 17, 20, 1, 6, 10, 9, 13, 19}

    for _, d := range results {
        // Imagine this is a long running operation, perhaps another
        // REST API call
        log.Printf("Waiting for %d seconds\n", d)
        time.Sleep(time.Second * time.Duration(d))
    }

    log.Printf("Total time taken: %s\n", time.Now().Sub(start))
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example 1&lt;/p&gt;

&lt;p&gt;You can see this eaxmple code, along with all the others in this page &lt;a href="https://github.com/dnnrly/sempool/"&gt;here&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This waits quite a while then gives the output:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/03 23:31:19 Waiting for 10 seconds
2018/10/03 23:31:29 Waiting for 15 seconds
2018/10/03 23:31:44 Waiting for 8 seconds
2018/10/03 23:31:52 Waiting for 3 seconds
2018/10/03 23:31:55 Waiting for 17 seconds
2018/10/03 23:32:12 Waiting for 20 seconds
2018/10/03 23:32:32 Waiting for 1 seconds
2018/10/03 23:32:33 Waiting for 6 seconds
2018/10/03 23:32:39 Waiting for 10 seconds
2018/10/03 23:32:49 Waiting for 9 seconds
2018/10/03 23:32:58 Waiting for 13 seconds
2018/10/03 23:33:11 Waiting for 19 seconds
2018/10/03 23:33:30 Total time taken: 2m11.012685s

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Over 2 minutes? Surely we could make this faster?&lt;/p&gt;

&lt;h2&gt;
  
  
  Adding goroutines
&lt;/h2&gt;

&lt;p&gt;What’s the simplest way to make this faster?&lt;/p&gt;

&lt;p&gt;It’s to make all the API calls at the same time. Let’s pretend we’re doing that in our example and use go routines to parralelise that work.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for _, d := range results {
    go func() {
        // Imagine this is a long running operation, perhaps another
        // REST API call
        log.Printf("Waiting for %d seconds\n", d)
        time.Sleep(time.Second * time.Duration(d))
    } ()
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example 2&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s look at what this gives us:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/05 20:53:11 Waiting for 1 seconds
2018/10/05 20:53:11 Waiting for 17 seconds
2018/10/05 20:53:11 Waiting for 19 seconds
2018/10/05 20:53:11 Waiting for 19 seconds
2018/10/05 20:53:11 Waiting for 19 seconds
2018/10/05 20:53:11 Waiting for 19 seconds
2018/10/05 20:53:11 Total time taken: 571µs

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Errrrrm, that’s not right! It’s not obvious but what I think is happening is that the value of &lt;code&gt;d&lt;/code&gt; is being modified &lt;em&gt;while&lt;/em&gt; the different goroutines are running, so several of them accidentally pick up the same value, that’s different from the value of &lt;code&gt;d&lt;/code&gt; when each on was launched. And then all of the goroutines end and the program exits before the &lt;code&gt;log&lt;/code&gt; package has written everything to the console.&lt;/p&gt;

&lt;h2&gt;
  
  
  Don’t end early
&lt;/h2&gt;

&lt;p&gt;We need a way to wait until all of the threads are done. For this, let’s use a &lt;a href="https://golang.org/pkg/sync/#WaitGroup"&gt;&lt;code&gt;sync.WaitGroup&lt;/code&gt;&lt;/a&gt;. This will allow us to safely track the number of goroutines that have been created and then wait until they done.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var wg sync.WaitGroup

for _, d := range results {
    wg.Add(1)

    go func() {
        defer wg.Done()

        // Imagine this is a long running operation, perhaps another
        // REST API call
        log.Printf("Waiting for %d seconds\n", d)
        time.Sleep(time.Second * time.Duration(d))
    } ()
}

wg.Wait()

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example 3&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;This time we get this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/05 21:43:57 Waiting for 6 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:43:57 Waiting for 19 seconds
2018/10/05 21:44:16 Total time taken: 19.003385s

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Well at least we’re getting the correct number of log entries and the time looks about right.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using correct values across goroutines
&lt;/h2&gt;

&lt;p&gt;This one should be a little easier, we just need to make sure that we pass in the data to the goroutine function that we’re invoking. Right?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;for _, d := range results {
    wg.Add(1)

    go func(secs int) {
        defer wg.Done()

        // Imagine this is a long running operation, perhaps another
        // REST API call
        log.Printf("Start waiting for %d seconds\n", secs)
        time.Sleep(time.Second * time.Duration(secs))
        log.Printf("Finished waiting for %d seconds\n", secs)
    } (d)
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example 4&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Look! We ran them all in order, and they finished when they were done! :)&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/05 22:21:20 Start waiting for 19 seconds
2018/10/05 22:21:20 Start waiting for 20 seconds
2018/10/05 22:21:20 Start waiting for 3 seconds
2018/10/05 22:21:20 Start waiting for 17 seconds
2018/10/05 22:21:20 Start waiting for 10 seconds
2018/10/05 22:21:20 Start waiting for 1 seconds
2018/10/05 22:21:20 Start waiting for 8 seconds
2018/10/05 22:21:20 Start waiting for 6 seconds
2018/10/05 22:21:20 Start waiting for 15 seconds
2018/10/05 22:21:20 Start waiting for 9 seconds
2018/10/05 22:21:20 Start waiting for 13 seconds
2018/10/05 22:21:20 Start waiting for 10 seconds
2018/10/05 22:21:21 Finished waiting for 1 seconds
2018/10/05 22:21:23 Finished waiting for 3 seconds
2018/10/05 22:21:26 Finished waiting for 6 seconds
2018/10/05 22:21:28 Finished waiting for 8 seconds
2018/10/05 22:21:29 Finished waiting for 9 seconds
2018/10/05 22:21:30 Finished waiting for 10 seconds
2018/10/05 22:21:30 Finished waiting for 10 seconds
2018/10/05 22:21:33 Finished waiting for 13 seconds
2018/10/05 22:21:35 Finished waiting for 15 seconds
2018/10/05 22:21:37 Finished waiting for 17 seconds
2018/10/05 22:21:39 Finished waiting for 19 seconds
2018/10/05 22:21:40 Finished waiting for 20 seconds
2018/10/05 22:21:40 Total time taken: 20.003293s

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Great…but…they all run at once. Let’s pretend that you’re trying to call a microservice that has some serious perforance issues so making all of those calls at the same time could cause problems. I know, I know, 12 calls at once isn’t really much but let’s pretend that it is. Well we say pretend, I’ve seen real life services in Production that would struggle for many different reasons. Something that I’ve seen more than once is exponential performance drop off - increasing the number of connections or requests increases response times exponentially. And watch out, it’s surprisingly easy to do if you’re not careful!&lt;/p&gt;

&lt;h2&gt;
  
  
  Limiting the number of concurrent requests
&lt;/h2&gt;

&lt;p&gt;So here we get in to some proper computer-y stuff. Ideally we would use a &lt;a href="https://en.wikipedia.org/wiki/Thread_pool"&gt;thread pool&lt;/a&gt; so that only a certain number of operations can be carried out at the same time. But this is Go and we’re not really using threads. So what else can we use?&lt;/p&gt;

&lt;p&gt;What we need here is to maintain a count of how many goroutines are active right now and stop more from running so we don’t exceed that magic number. We need to block goroutines when we don’t have enough capactity. We need to use a &lt;a href="https://en.wikipedia.org/wiki/Semaphore_(programming)"&gt;semaphore&lt;/a&gt;!&lt;/p&gt;

&lt;p&gt;There are a few approaches to using semaphores but fortunately we’re using Go so we can take advantage of channels to give us the correct behaviour without having to explicitly use a thread pool.&lt;/p&gt;

&lt;p&gt;For this we need to create a &lt;em&gt;buffered channel&lt;/em&gt;, so a channel with certain number of slots that can be filled at the same time. But what do we fill it with? Does it matter? Well it doesn’t, really. Did you know you can pass an empty &lt;code&gt;struct&lt;/code&gt; in to channel? Lot’s of details &lt;a href="http://www.golangpatterns.info/concurrency/semaphores"&gt;here&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Let’s see how this works:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var wg sync.WaitGroup
sem := make(chan struct{}, 3)

for _, d := range results {
        wg.Add(1)

        go func(wait int) {
                defer func() {
                        wg.Done()

                        // Release the semaphore resource
                        &amp;lt;-sem
                }()

                // Aquire a single semaophore resource
                sem &amp;lt;- struct{}{}

                // Imagine this is a long running operation, perhaps another
                // REST API call
                log.Printf("Start waiting for %d seconds\n", wait)
                time.Sleep(time.Second * time.Duration(wait))
                log.Printf("Finished waiting for %d seconds\n", wait)
        }(d)
}

wg.Wait()

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So what does this look like?&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/06 00:12:09 Start waiting for 19 seconds
2018/10/06 00:12:09 Start waiting for 15 seconds
2018/10/06 00:12:09 Start waiting for 10 seconds
2018/10/06 00:12:19 Finished waiting for 10 seconds
2018/10/06 00:12:19 Start waiting for 3 seconds
2018/10/06 00:12:22 Finished waiting for 3 seconds
2018/10/06 00:12:22 Start waiting for 8 seconds
2018/10/06 00:12:24 Finished waiting for 15 seconds
2018/10/06 00:12:24 Start waiting for 17 seconds
2018/10/06 00:12:28 Finished waiting for 19 seconds
2018/10/06 00:12:28 Start waiting for 10 seconds
2018/10/06 00:12:30 Finished waiting for 8 seconds
2018/10/06 00:12:30 Start waiting for 6 seconds
2018/10/06 00:12:36 Finished waiting for 6 seconds
2018/10/06 00:12:36 Start waiting for 20 seconds
2018/10/06 00:12:38 Finished waiting for 10 seconds
2018/10/06 00:12:38 Start waiting for 9 seconds
2018/10/06 00:12:41 Finished waiting for 17 seconds
2018/10/06 00:12:41 Start waiting for 13 seconds
2018/10/06 00:12:47 Finished waiting for 9 seconds
2018/10/06 00:12:47 Start waiting for 1 seconds
2018/10/06 00:12:48 Finished waiting for 1 seconds
2018/10/06 00:12:54 Finished waiting for 13 seconds
2018/10/06 00:12:56 Finished waiting for 20 seconds
2018/10/06 00:12:56 Total time taken: 47.005534s

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example 5&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;We did it! Admittedly not as quick as earlier, but we only do 3 things at once and therefore not totally overloading our pretend fragile API.&lt;/p&gt;

&lt;h2&gt;
  
  
  Passing data on to the next step
&lt;/h2&gt;

&lt;p&gt;Now it wouldn’t it be nice if after we make our calls to this API, we processed the results all together? Maybe we’re trying to aggregate something or use the individual bits of data to draw a pretty picture.&lt;/p&gt;

&lt;p&gt;Let’s use another channel to pass these response on.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;var wg sync.WaitGroup
sem := make(chan struct{}, 3)
responses := make(chan int)

for _, d := range results {
        wg.Add(1)

        go func(wait int) {
                defer func() {
                        // Release the semaphore resource
                        &amp;lt;-sem
                        wg.Done()
                }()

                // Aquire a single semaophore resource
                sem &amp;lt;- struct{}{}

                // Imagine this is a long running operation, perhaps another
                // REST API call
                log.Printf("Start waiting for %d seconds\n", wait)
                time.Sleep(time.Second * time.Duration(wait))
                log.Printf("Finished waiting for %d seconds\n", wait)

                responses &amp;lt;- wait / 2
        }(d)
}

wg.Wait()

for r := range responses {
        log.Printf("Got result %d", r)
}

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;Example 6&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Which gives…&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/06 00:37:04 Start waiting for 19 seconds
2018/10/06 00:37:04 Start waiting for 17 seconds
2018/10/06 00:37:04 Start waiting for 15 seconds
2018/10/06 00:37:19 Finished waiting for 15 seconds
2018/10/06 00:37:21 Finished waiting for 17 seconds
2018/10/06 00:37:23 Finished waiting for 19 seconds
fatal error: all goroutines are asleep - deadlock!

goroutine 1 [semacquire]:
sync.runtime_Semacquire(0xc0000120a8)
        /usr/local/go/src/runtime/sema.go:56 +0x39
sync.(*WaitGroup).Wait(0xc0000120a0)
        /usr/local/go/src/sync/waitgroup.go:130 +0x64
main.main()
        /home/dnnrly/projects-host/sempool/example6/main.go:42 +0x184

goroutine 4 [chan send]:
main.main.func1(0xc00009e000, 0xc0000120a0, 0xc00009e060, 0xa)
        /home/dnnrly/projects-host/sempool/example6/main.go:30 +0x6d
created by main.main
        /home/dnnrly/projects-host/sempool/example6/main.go:22 +0x158

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;blockquote&gt;
&lt;p&gt;I’ve abreviated this log output, there is a lot of it.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Well, that’s clearly not good! We have a &lt;a href="https://en.wikipedia.org/wiki/Deadlock"&gt;deadlock&lt;/a&gt; and looking at the lines of code indicated, it’s a problem with waiting for the &lt;code&gt;sync.WaitGroup&lt;/code&gt; to finish and trying to &lt;em&gt;acquire&lt;/em&gt; the semaphore. If you run this example yourself you can see it tells us which lines we are blocking on.&lt;/p&gt;

&lt;p&gt;Hmmm, the first thing I tried didn’t work. You, reader - go do something else for a couple of hours while I figure this out.&lt;/p&gt;

&lt;h2&gt;
  
  
  Moving to mutexes
&lt;/h2&gt;

&lt;p&gt;So I am writing this literally 8 hours afte that last paragraph. Admittedly I was doing other things during those 8 hours but still, it took some figuring out. To help me out, I created an alterntive to example 6 with logging. Take a look at the &lt;a href="https://github.com/dnnrly/sempool/"&gt;repo&lt;/a&gt; if you’re interested.&lt;/p&gt;

&lt;p&gt;It appears that the problem is that if we use channels to store the ‘result’ of our calculation then we have a problem. Essentially by using &lt;code&gt;make(chan int)&lt;/code&gt;, we are creating another buffered channel. But this time, with zero slots - it needs to be read from immediately or else it will block. Which is exactly what happened. Our worker goroutine blocked immediately, meaning that we never get to the end of the goroutines and we deadlock.&lt;/p&gt;

&lt;p&gt;It looks like I made the classic mistake of trying to use channels to synchronize rather than comminicate. What we really want to do in this particular situation is append to a slice so that it can be processed later on. To do this we have to make sure that we don’t suffer from other race conditions that might mess up the append operation - the &lt;code&gt;append&lt;/code&gt; operation is definitely not &lt;a href="https://en.wikipedia.org/wiki/Thread_safety"&gt;thread safe&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;To get around this, we use a &lt;code&gt;sync.Mutex&lt;/code&gt; to force all of the goroutines to perform the append one at a time.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        var wg sync.WaitGroup
        sem := make(chan struct{}, 3)
        responses := []int{}
        mutex := &amp;amp;sync.Mutex{}

        for _, d := range results {
                wg.Add(1)

                go func(wait int) {
                        defer func() {
                                // Release the semaphore resource
                                &amp;lt;-sem
                                wg.Done()
                        }()

                        // Aquire a single semaophore resource
                        sem &amp;lt;- struct{}{}

                        // Imagine this is a long running operation, perhaps another
                        // REST API call
                        log.Printf("Start waiting for %d seconds\n", wait)
                        time.Sleep(time.Second * time.Duration(wait))
                        log.Printf("Finished waiting for %d seconds\n", wait)

                        mutex.Lock()
                        responses = append(responses, wait/2)
                        mutex.Unlock()
                }(d)
        }

        wg.Wait()

        for _, r := range responses {
                log.Printf("Got result %d", r)
        }

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;And look upon the glorious success:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2018/10/06 22:16:48 Start waiting for 8 seconds
2018/10/06 22:16:48 Start waiting for 19 seconds
2018/10/06 22:16:48 Start waiting for 10 seconds
2018/10/06 22:16:56 Finished waiting for 8 seconds
2018/10/06 22:16:56 Start waiting for 17 seconds
2018/10/06 22:16:58 Finished waiting for 10 seconds
2018/10/06 22:16:58 Start waiting for 3 seconds
2018/10/06 22:17:01 Finished waiting for 3 seconds
2018/10/06 22:17:01 Start waiting for 15 seconds
2018/10/06 22:17:07 Finished waiting for 19 seconds
2018/10/06 22:17:07 Start waiting for 10 seconds
2018/10/06 22:17:13 Finished waiting for 17 seconds
2018/10/06 22:17:13 Start waiting for 1 seconds
2018/10/06 22:17:14 Finished waiting for 1 seconds
2018/10/06 22:17:14 Start waiting for 6 seconds
2018/10/06 22:17:16 Finished waiting for 15 seconds
2018/10/06 22:17:16 Start waiting for 9 seconds
2018/10/06 22:17:17 Finished waiting for 10 seconds
2018/10/06 22:17:17 Start waiting for 20 seconds
2018/10/06 22:17:20 Finished waiting for 6 seconds
2018/10/06 22:17:20 Start waiting for 13 seconds
2018/10/06 22:17:25 Finished waiting for 9 seconds
2018/10/06 22:17:33 Finished waiting for 13 seconds
2018/10/06 22:17:37 Finished waiting for 20 seconds
2018/10/06 22:17:37 Got result 4
2018/10/06 22:17:37 Got result 5
2018/10/06 22:17:37 Got result 1
2018/10/06 22:17:37 Got result 9
2018/10/06 22:17:37 Got result 8
2018/10/06 22:17:37 Got result 0
2018/10/06 22:17:37 Got result 7
2018/10/06 22:17:37 Got result 5
2018/10/06 22:17:37 Got result 3
2018/10/06 22:17:37 Got result 4
2018/10/06 22:17:37 Got result 6
2018/10/06 22:17:37 Got result 10
2018/10/06 22:17:37 Total time taken: 49.006433s

&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;Ay you can tell, I’m rather happy with this result.&lt;/p&gt;

&lt;h1&gt;
  
  
  Conclusion
&lt;/h1&gt;

&lt;blockquote&gt;

&lt;pre class="highlight plaintext"&gt;&lt;code&gt;The 2 hardest things in computing are naming things, concurrency and off-by-one errors.

&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;&lt;em&gt;Someone famous in the Go community, on Twitter (I forget who)&lt;/em&gt;&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So we’ve looked at how we can do work (make API requests?) concurrently and what we can do to limit just how concurrent we want to be. We then looked at how we can pass results from this concurrent work on to the next step in the process, without accidentally reading data in corruptly or causing a deadlocks.&lt;/p&gt;

</description>
      <category>go</category>
      <category>threads</category>
    </item>
  </channel>
</rss>
