<?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: Jonathan Hall</title>
    <description>The latest articles on Forem by Jonathan Hall (@jhall).</description>
    <link>https://forem.com/jhall</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%2F287061%2Fec33a650-03c8-4167-970b-8590903f76cb.jpg</url>
      <title>Forem: Jonathan Hall</title>
      <link>https://forem.com/jhall</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/jhall"/>
    <language>en</language>
    <item>
      <title>Three things that can go before a package clause in Go</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Mon, 14 Oct 2024 23:09:12 +0000</pubDate>
      <link>https://forem.com/jhall/three-things-that-can-go-before-a-package-clause-in-go-39b</link>
      <guid>https://forem.com/jhall/three-things-that-can-go-before-a-package-clause-in-go-39b</guid>
      <description>&lt;p&gt;&lt;em&gt;This post is an &lt;a href="https://boldlygo.tech/archive/2024-10-14-packages/" rel="noopener noreferrer"&gt;excerpt&lt;/a&gt; from my email list, &lt;strong&gt;Boldy Go: Daily&lt;/strong&gt;. &lt;a href="https://boldlygo.tech/daily/" rel="noopener noreferrer"&gt;Join for more content like this every day&lt;/a&gt;.&lt;/em&gt;&lt;/p&gt;




&lt;p&gt;If you’ve done any Go coding at all, you’ve seen at least one package clause:&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;And you probably know that it comes at the top of each Go source file.&lt;/p&gt;

&lt;p&gt;But did you know there are three other things that &lt;em&gt;may&lt;/em&gt; come first?  Let's look at all three:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;p&gt;Comments, including GoDoc. It's good practice to include a descriptive GoDoc paragraph &lt;em&gt;immediately&lt;/em&gt; before the &lt;code&gt;package&lt;/code&gt; clause (i.e. with no blank lines between). You need only do this in a single file (in case of a multi-file package).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Package foo Foos all the Bars.&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;Build constraints and other directives (these are treated as comments, but are worth mentioning separately).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;//go:build !js&lt;/span&gt;

&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;foo&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;In this example, we tell the compiler to ignore this file when building for a JS target (i.e. WebAssembly or GopherJS).&lt;/p&gt;
&lt;/li&gt;
&lt;li&gt;
&lt;p&gt;A shebang line (only as the very first line of the file).&lt;br&gt;
&lt;/p&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;!/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;


&lt;p&gt;What?!&lt;/p&gt;

&lt;p&gt;Didn't know that was possible?&lt;/p&gt;

&lt;p&gt;This actually isn't a Go thing at all, it's more a shell thing. But all common Unix/Linux shells will recognize such a line, and interpret it as the name of an interpretor to pass the file to.  You really should not ever need this in Go, but some folks have fun writing Go for shell-script types of tasks. If that describes you, this will apply. I included this here mostly for completeness sake, not as an endorsement of this approach. 😉&lt;/p&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What if we put all three together, just for fun?&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="err"&gt;#&lt;/span&gt;&lt;span class="o"&gt;!/&lt;/span&gt;&lt;span class="n"&gt;usr&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;local&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="n"&gt;bin&lt;/span&gt;&lt;span class="o"&gt;/&lt;/span&gt;&lt;span class="k"&gt;go&lt;/span&gt; &lt;span class="n"&gt;run&lt;/span&gt;

&lt;span class="c"&gt;// this comment does nothing special. It's not GoDoc, becuase&lt;/span&gt;
&lt;span class="c"&gt;// there's no package clause or declaration on the next line,&lt;/span&gt;
&lt;span class="c"&gt;// and it's not a build constraint.&lt;/span&gt;

&lt;span class="c"&gt;//go:build !js&lt;/span&gt;

&lt;span class="c"&gt;//go:generate /path/to/utility&lt;/span&gt;

&lt;span class="c"&gt;// Package main is a utility that does something interesting.&lt;/span&gt;
&lt;span class="k"&gt;package&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



</description>
      <category>go</category>
      <category>shell</category>
    </item>
    <item>
      <title>Don't panic!</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Thu, 28 Mar 2024 08:56:18 +0000</pubDate>
      <link>https://forem.com/jhall/dont-panic-3g09</link>
      <guid>https://forem.com/jhall/dont-panic-3g09</guid>
      <description>&lt;p&gt;&lt;em&gt;This post comes from my daily email list: Boldly Go! Daily. &lt;a href="https://boldlygo.tech/daily"&gt;Sign up to learn a bit more about Go every day!&lt;/a&gt;&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;--&lt;/p&gt;

&lt;p&gt;Don’t panic.&lt;/p&gt;

&lt;p&gt;Don’t panic is such ubiquitous Go advice that it’s one of the famous &lt;a href="https://go-proverbs.github.io/"&gt;Go proverbs&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;So why do we have a built-in &lt;code&gt;panic&lt;/code&gt; function if we’re not supposed to use it?&lt;/p&gt;

&lt;p&gt;Well, it’s not so much that it’s never appropriate to use, as much as it’s often heavily overused. Especially by programmers who are accustomed to using exceptions and try/catch blocks to manage control flow.&lt;/p&gt;

&lt;p&gt;Don’t do that!&lt;/p&gt;

&lt;p&gt;At the moment I’m helping one client with a massive refactor of their application to remove the problematic, non-idiomatic pattern of using &lt;code&gt;panic&lt;/code&gt; rather than proper Go error handling.&lt;/p&gt;

&lt;p&gt;I’m sure we’ll talk a lot more about this in the future, but probably the most important reason not to panic is that it’s very non-obvious. This problem exists in languages that uses exceptions for error handling, too (and is why Go’s design doesn’t encourage this pattern). Consider this code (taken from the above mentioned client’s code base, with names edited to protect the innocent):&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;CreateRecordWithIDAndType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;typ&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceType&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;userID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;appctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticatedUserIdOptional&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;userID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;recordReq&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;RecordRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ActionRequest&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ActionRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;learnType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;id&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;CreateRecordWithCDP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recordReq&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;Here’s the question: Can the call to &lt;code&gt;CreateRecordWithCDP&lt;/code&gt; result in an error condition?&lt;/p&gt;

&lt;p&gt;It’s impossible to be sure. Although we have one strong clue: It accepts a &lt;code&gt;context.Context&lt;/code&gt; value, which is often, though not always, an indication that the function call may block, and be terminated early if the context is cancelled. This would suggest that an error state is possible. Although the context could just be used to read a value, in which case it may legitimately not be possible for &lt;code&gt;CreateRecordWithCDP&lt;/code&gt; to result in an error condition. It also doesn’t return anything, so whatever it’s “creating”, presumably is stored somewhere–probably in a database. And database operations, as a rule, can err.&lt;/p&gt;

&lt;p&gt;In any case, since we don’t know, we’re forced to either investigate &lt;code&gt;CreateRecordWithCDP&lt;/code&gt; (and any functions it calls) to determine if it might panic, or just play it safe, and add a deferred &lt;code&gt;recover&lt;/code&gt; before we call it.&lt;/p&gt;

&lt;p&gt;Wouldn’t it be much easier if we had some obvious indication? Perhaps like this new version?&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;CreateRecordWithIDAndType&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt; &lt;span class="n"&gt;context&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;id&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ID&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;typ&lt;/span&gt; &lt;span class="n"&gt;model&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResourceType&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;userID&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;appctx&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AuthenticatedUserIdOptional&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&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;userID&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Valid&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;recordReq&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;RecordRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;ActionRequest&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;ActionRequest&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;Type&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;learnType&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
                &lt;span class="n"&gt;Id&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;   &lt;span class="n"&gt;id&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;CreateRecordWithCDP&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;ctx&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;recordReq&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This make the fact that calling &lt;code&gt;CreateRecordWithCDP&lt;/code&gt; (and in turn &lt;code&gt;CreateRecordWithIDAndType&lt;/code&gt;) can result in an error condition. And it makes programming to use these functions much simpler, and eliminates a lot of guesswork.&lt;/p&gt;

&lt;p&gt;Of course, this does lead to the situation many complain about, of cluttering your code with &lt;code&gt;if err != nil { ... }&lt;/code&gt;. But IMO, while this is a bit annoying to type, typing is a very small price to pay for the clarity it provides.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Error handling in Go web apps shouldn't be so awkward</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Wed, 10 Jan 2024 15:18:21 +0000</pubDate>
      <link>https://forem.com/jhall/error-handling-in-go-web-apps-shouldnt-be-so-awkward-4e2k</link>
      <guid>https://forem.com/jhall/error-handling-in-go-web-apps-shouldnt-be-so-awkward-4e2k</guid>
      <description>&lt;p&gt;In this post I’m going to describe an error-handling pattern I’ve found to be fairly elegant when writing REST, gRPC, or other services in Go. I have three goals in writing this post:&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;To explain the pattern I’ve implemented for a few clients, so that others developing on the same codebase will understand it.&lt;/li&gt;
&lt;li&gt;To give others a pattern they may wish to implement in their own applications.&lt;/li&gt;
&lt;li&gt;To solicit feedback. Is there a better pattern out there I haven’t seen yet? Are there tweaks I can make to this pattern to make it better?&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  The problem
&lt;/h2&gt;

&lt;p&gt;Before I explain the pattern I use, let me explain what it replaces, so that we might understand the problems it's meant to solve.&lt;/p&gt;

&lt;p&gt;Let's look at a simple HTTP handler, using the standard library's &lt;a href="https://pkg.go.dev/net/http#HandlerFunc"&gt;HandlerFunc&lt;/a&gt; pattern, which simply fetches a widget record from the database, and serves it to the client as JSON&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseForm&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="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;id&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"widget_id"&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;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widget&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;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNoRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
        &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widgetJSON&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&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;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widgetJSON&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;While this should be a more or less realistic example, it's intentionally over-simplified from what I typically find in production services. In particular, I've never seen &lt;a href="https://pkg.go.dev/net/http#Error"&gt;&lt;code&gt;http.Error&lt;/code&gt;&lt;/a&gt; used in a real service. Much more likely, you'll have a custom error format you want to send back. Possibly utilizing a JSON error response, with some additional error context or internal error codes, etc.  Or maybe you want to render the error as HTML. In any case, I'll assume your app replaces the &lt;code&gt;http.Error()&lt;/code&gt; call with something more sophisticated. Which likely means your code is even more annoying and repetitive than what I've shown above.&lt;/p&gt;

&lt;p&gt;That aside, let me call out a few specific problems I see with the above code:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;The error handling is repetitive, and non-idiomatic.  Go is (in)famous for its &lt;code&gt;if err != nil { return err }&lt;/code&gt; idiom. Yet we can't even use &lt;em&gt;that&lt;/em&gt; here, because the &lt;a href="https://pkg.go.dev/net/http#HandlerFunc"&gt;HandlerFunc&lt;/a&gt; signature doesn't return an error.  Instead, for every error, we must (a) serve the error, and separately (b) return.&lt;/li&gt;
&lt;li&gt;We must explicitly handle the HTTP status for every error case. If you have dozens or hundreds of handlers (and you probably do), this quickly becomes repetitive, and error-prone. There's no DRY here. In a single handler like this, maybe it's not a big deal. But it would be nice if we had some sort of default HTTP status code for an error—probably 500 / Internal Server Error.&lt;/li&gt;
&lt;li&gt;This handler has to concern itself with database internals. In particular, it checks whether we received a &lt;a href="https://pkg.go.dev/database/sql#pkg-variables"&gt;&lt;code&gt;sql.ErrNoRows&lt;/code&gt;&lt;/a&gt; error. The HTTP handler should be completely database agnostic, so this detail should not need to be exposed here. This is some ugly tight-coupling we can get rid of.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What if, instead...
&lt;/h2&gt;

&lt;p&gt;What if, instead:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;for every error, we could simply &lt;code&gt;return err&lt;/code&gt;, and the right thing would happen? The error would be rendered to the proper format, and sent to the user?&lt;/li&gt;
&lt;li&gt;the magic that renders the error would know the proper HTTP status to set, too?  400 for invalid input, 404 for not found, 401 for unauthorized access, etc?&lt;/li&gt;
&lt;li&gt;the data store, whether an SQL database, or MongoDB, or the filesystem, would just tell us "this error means not found", and that could be automatically converted to a 404 instead of the handler knowing the implementation details?&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;The pattern I'm about to describe gives us all of these things. Not only that, but it enables a number of other emergant patterns which are quite powerful as well. I'll mention some of them at the end, and may write more extensively about some of them later on (let me know if that would interest you).&lt;/p&gt;

&lt;h2&gt;
  
  
  Idiomatic error handling
&lt;/h2&gt;

&lt;p&gt;The three behaviors I've described that we want all depend on two things, the first of which is "idiomatic error handling".  We need to be able to simply &lt;code&gt;return err&lt;/code&gt; in our handlers.  Unfortunately, the standard libray doesn't give us this.  But some third-party frameworks do. The most popular one I'm familiar with is &lt;a href="https://echo.labstack.com/"&gt;labstack echo&lt;/a&gt;, whose &lt;a href="https://pkg.go.dev/github.com/labstack/echo/v4#HandlerFunc"&gt;&lt;code&gt;HandlerFunc&lt;/code&gt;&lt;/a&gt; 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;type&lt;/span&gt; &lt;span class="n"&gt;HandlerFunc&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;c&lt;/span&gt; &lt;span class="n"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But I don't believe you should need to adopt a heavy framework like Echo just to get handy error-handling primitives.  So you can do this yourself.  Here's a simple adapter function pattern you can use:&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;// customHandler converts an error-returning handler to a standard http.HandlerFunc.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;customHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&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;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// Wait, alwyas 500? More on that later&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;With such an adapter function, our earlier handler gets simplified 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="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseForm&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="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;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;id&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"widget_id"&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;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widget&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;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widgetJSON&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&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;err&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widgetJSON&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;Of course this requires that we actually &lt;em&gt;use&lt;/em&gt; the adapter function when setting up our routes:&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;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/widget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;customHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Of course we've also actually &lt;em&gt;broken&lt;/em&gt; this endpoint. It now treats &lt;em&gt;all&lt;/em&gt; errors as internal server errors. So we'll address that next.&lt;/p&gt;

&lt;h2&gt;
  
  
  But first, an experiment I'm working on
&lt;/h2&gt;

&lt;p&gt;But before we do, I want to call out an experimental library I'm working on, with the hope it may eventually become an official proposal to the standard library (although I think it's a long shot it would be accepted) to extend the definition of the &lt;a href="https://pkg.go.dev/net/http#HandlerFunc"&gt;&lt;code&gt;http.HandlerFunc&lt;/code&gt;&lt;/a&gt; type to include an optional error return value. The library is &lt;a href="https://pkg.go.dev/gitlab.com/flimzy/httpe"&gt;gitlab.com/flimzy/httpe&lt;/a&gt;, and it adds -&lt;code&gt;WithError&lt;/code&gt; variants to &lt;code&gt;http.Handler&lt;/code&gt;, &lt;code&gt;http.HandlerFunc&lt;/code&gt;, &lt;code&gt;ServeHTTP&lt;/code&gt;, and related middlewares.  It's based on work I've been using for years with clients, but now living in its own stand-alone library for easy inclusion, if you wish.&lt;/p&gt;

&lt;p&gt;If you choose to use this library, the new version of the handler remains unchanged, but in places of calling &lt;code&gt;customHandler&lt;/code&gt;, you could 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;import&lt;/span&gt; &lt;span class="s"&gt;"gitlab.com/flimzy/httpe"&lt;/span&gt;

&lt;span class="n"&gt;mux&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Handle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/widget"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ToHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The main advantage to the &lt;code&gt;httpe&lt;/code&gt; library over your own custom handler is that it provides support for middleware adapters, and inter-mixing standard and error-enabled handlers, with some behind-the-scenes error propagation. But that's beyond the scope of this post.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to handle different HTTP statuses
&lt;/h2&gt;

&lt;p&gt;The second thing these improvements depends on is some way to specify an HTTP status. We've observed that while this new handler pattern makes error handling &lt;em&gt;simpler&lt;/em&gt;, it also breaks it, by treating all errors as 500 / Internal Server Error (or whatever arbitrary status you set in your &lt;code&gt;customHandler&lt;/code&gt; function).  Let's address that now.&lt;/p&gt;

&lt;h3&gt;
  
  
  Errors are interfaces
&lt;/h3&gt;

&lt;p&gt;Recall that in Go, the &lt;code&gt;error&lt;/code&gt; type is an interface type, define as:&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="kt"&gt;error&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;Error&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This is powerful, because it means we can create our own custom error types. And what's more, for our purposes, we can &lt;em&gt;extend&lt;/em&gt; the error type to include other methods.&lt;/p&gt;

&lt;p&gt;We want to take advantage of both of these capabilities to create a custom error type that includes an HTTP status, and add a method to expose that status.  Here's the simple custom type we'll be using:&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;statusError&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now already this is a "complete" error type. It already satisfies the &lt;code&gt;error&lt;/code&gt; interface by virtue of embedding the &lt;code&gt;error&lt;/code&gt; type (so its methods are promoted to our type's methods). And it includes a status code.  But we need a couple more pieces to make this complete.  First, let's add an &lt;code&gt;Unwrap&lt;/code&gt; method, to allow &lt;a href="https://pkg.go.dev/errors#Unwrap"&gt;&lt;code&gt;errors.Unwrap&lt;/code&gt;&lt;/a&gt; and the related &lt;a href="https://pkg.go.dev/errors#Is"&gt;&lt;code&gt;errors.Is&lt;/code&gt;&lt;/a&gt; and &lt;a href="https://pkg.go.dev/errors#As"&gt;&lt;code&gt;errors.As&lt;/code&gt;&lt;/a&gt;, etc, to work properly:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;statusError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Unwrap&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&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;And now we also want to add a method to expose the included status.  Strictly speaking, this isn't &lt;em&gt;necessary&lt;/em&gt;.  You &lt;em&gt;can&lt;/em&gt; get at the status code by type-converting an error back to the &lt;code&gt;statusError&lt;/code&gt; type with a type assertion, or with the use of &lt;code&gt;errors.Is&lt;/code&gt; or &lt;code&gt;errors.As&lt;/code&gt;. But it's a bit cubersome, and requires exporting the field (unless your entire application is in a single package--I sure hope that's not the case!) Further, by exposing the status via an interface method, we have the freedom to use multiple implementations of our custom error type, which is something I virtually always do.  So let's add that detail:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;statusError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;HTTPStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now, you could name your method whatever you want. I've settled on &lt;code&gt;HTTPStatus&lt;/code&gt;, after initially using simply &lt;code&gt;Status()&lt;/code&gt;, because it's less ambiguous, but still short enough not to be annoying.  You can just as eaisly use any other method (or multiple methods).  For example, maybe you want &lt;code&gt;JSONRPCStatus()&lt;/code&gt; if you're building a JSON-RPC service. Or if you're building a gRPC service, there's already an interface defined for you: &lt;code&gt;GRPCStatus() *status.Status&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Using our custom error type
&lt;/h2&gt;

&lt;p&gt;Now that we have our &lt;code&gt;statusError&lt;/code&gt; type, let's incorporate it into our handler, to un-break our status code handling:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseForm&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="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;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;id&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"widget_id"&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;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widget&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;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widgetJSON&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&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;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widgetJSON&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 now we've (mostly) unbroken our status codes.  The one exception is the database call. We treat all errors as status 500, when we should treat a missing widget as 404.  The solution here is to make our data access layer aware of these new error types:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Widget&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;widget&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNoRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusNotFound&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;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;widget&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;One last thing: We need to update our &lt;code&gt;customHandler&lt;/code&gt; to understand this new error 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="c"&gt;// customHandler converts an error-returning handler to a standard http.HandlerFunc.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;customHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&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;var&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
            &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;statusErr&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;error&lt;/span&gt;
                &lt;span class="n"&gt;HTTPStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;As&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statusErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;statusErr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
            &lt;span class="p"&gt;}&lt;/span&gt;
            &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;status&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;Okay... so now we're back to a fully-functional widget handler.  And we've also decoupled our databaes logic from our HTTP handler. So that's a win.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further improvments
&lt;/h2&gt;

&lt;p&gt;But our handler is still kind of ugly, with a bunch of repeated &lt;code&gt;customErrror{}&lt;/code&gt; structs. We also have both our handler and our data access layer depending on a concrete &lt;code&gt;statusError&lt;/code&gt; type. Which isn't even exported, which implies that our data access layer and handler are in the same package. Ick. We really don't want that.  So let's move our custom error type to its own package. And we'll add a convenient and descriptive constructor function, as well.&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;apperr&lt;/span&gt; &lt;span class="c"&gt;// Use a descriptive name&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;statusError&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="kt"&gt;error&lt;/span&gt;
    &lt;span class="n"&gt;status&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;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;statusError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Unwrap&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="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&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;e&lt;/span&gt; &lt;span class="n"&gt;statusError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;HTTPStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt; &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;status&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;WithHTTPStatus&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="n"&gt;status&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="kt"&gt;error&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;statusError&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="o"&gt;:&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="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Now our handler can be updated to the slightly more readable:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;s&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Service&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="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="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ParseForm&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="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;apperr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithStatus&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;id&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;strconv&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Atoi&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Form&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"widget_id"&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;apperr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithStatus&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widget&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;s&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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;err&lt;/span&gt; &lt;span class="c"&gt;// No call to apperr.WithStatus here, as we trust the db has already set the appropriate status code for us&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;widgetJSON&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;json&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Marshal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widget&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;apperr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithStatus&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusBadRequest&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Header&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Set&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Content-Type"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"application/json"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;widgetJSON&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;h2&gt;
  
  
  Setting a default status
&lt;/h2&gt;

&lt;p&gt;We can do one other big improvement to this setup: Setting a default status.&lt;/p&gt;

&lt;p&gt;In fact, you may have noticed that our improved &lt;code&gt;customHandler&lt;/code&gt; func &lt;em&gt;has no default status&lt;/em&gt;. This means that if we pass it an error that doesn't include an HTTP status, it will try to serve an HTTP response with status of &lt;code&gt;0&lt;/code&gt;. Probably not ideal.&lt;/p&gt;

&lt;p&gt;Let's solve this problem by adding a helper function to our &lt;code&gt;apperr&lt;/code&gt; package, which can also be used from other places:&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;apperr&lt;/span&gt;

&lt;span class="c"&gt;// HTTPStatus returns the HTTP status included in err. If err is nil, this&lt;/span&gt;
&lt;span class="c"&gt;// function returns 0. If err is non-nil, and does not include an HTTP status,&lt;/span&gt;
&lt;span class="c"&gt;// a default value of [net/http.StatusInternalServerError] is returned.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;HTTPStatus&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="kt"&gt;int&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="m"&gt;0&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;statusErr&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;error&lt;/span&gt;
        &lt;span class="n"&gt;HTTPStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;As&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="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;statusErr&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;statusErr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPStatus&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusInternalServerError&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;With this new function in our pocket, our custom handler can be simplified and improved:&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;// customHandler converts an error-returning handler to a standard http.HandlerFunc.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;customHandler&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;f&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerFunc&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;return&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;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;f&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&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;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;apperr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPStatus&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;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 our handler can also be improved by omitting the call to &lt;code&gt;apierr.WithStatus&lt;/code&gt; when we want the default status of 500 / Internal Server Error.&lt;/p&gt;

&lt;h2&gt;
  
  
  Further improvements
&lt;/h2&gt;

&lt;p&gt;This is really only the beginning of what using an app-wide standard error extension and matching handlers can provide.&lt;/p&gt;

&lt;p&gt;The next areas I usually improve on apps where I implement this pattern is to add a couple standard middlewares:&lt;/p&gt;

&lt;h3&gt;
  
  
  Logging middleware
&lt;/h3&gt;

&lt;p&gt;A middleware to log, with an associated error, if relevant, is a great addition. And it eliminates the "need" to log an error every time it happens--just pass it to your caller, and let the middleware log it for you.  Here's a simplified example, using the function signatures in &lt;a href="https://pkg.go.dev/gitlab.com/flimzy/httpe"&gt;gitlab.com/flimzy/httpe&lt;/a&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;loggingMiddleware&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;logger&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;slog&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Logger&lt;/span&gt;&lt;span class="p"&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;next&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithError&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;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithErrorFunc&lt;/span&gt;&lt;span class="p"&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;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTPWithError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
        &lt;span class="n"&gt;status&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StatusOK&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;status&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;apperr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPStatus&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;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Error&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"request served with error"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"error"&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;span class="k"&gt;else&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="n"&gt;logger&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Info&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"request served"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"status"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;status&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"request"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&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;Keep in mind that a handler can still call &lt;code&gt;w.WriteHeader&lt;/code&gt; with a status distinct from that contained in &lt;code&gt;err&lt;/code&gt; (or even in the absence of an error). So a robust implementation will check for that as well.&lt;/p&gt;

&lt;h3&gt;
  
  
  Error-serving middleware
&lt;/h3&gt;

&lt;p&gt;An improvement over the &lt;code&gt;customHandler&lt;/code&gt; function shown above, is to move the error serving into a middleware.  This does require the &lt;code&gt;httpe&lt;/code&gt; package, or a similar implemenatation, that can work with middlewares.&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;serveErrors&lt;/span&gt;&lt;span class="p"&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;next&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithError&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;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithErrorFunc&lt;/span&gt;&lt;span class="p"&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;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTPWithError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&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;http&lt;/span&gt;&lt;span class="o"&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;w&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;Error&lt;/span&gt;&lt;span class="p"&gt;(),&lt;/span&gt; &lt;span class="n"&gt;apperr&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Status&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;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;h3&gt;
  
  
  Panc-recovery middleware
&lt;/h3&gt;

&lt;p&gt;Most web apps have this (or they should!), but a version that works with error-returning handlers can be nice, as it just has to convert panics to errors, rather than serving them directly:&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;serveErrors&lt;/span&gt;&lt;span class="p"&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;next&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithError&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;httpe&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HandlerWithErrorFunc&lt;/span&gt;&lt;span class="p"&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;w&lt;/span&gt; &lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ResponseWriter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;http&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Request&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="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="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="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;r&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="nb"&gt;recover&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt; &lt;span class="n"&gt;r&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;switch&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;r&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="k"&gt;type&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
                    &lt;span class="k"&gt;case&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt;&lt;span class="o"&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;t&lt;/span&gt;
                    &lt;span class="k"&gt;default&lt;/span&gt;&lt;span class="o"&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;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;"%v"&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;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;next&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ServeHTTPWithError&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;w&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;r&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;h2&gt;
  
  
  Domain-specific error codes
&lt;/h2&gt;

&lt;p&gt;What's better than having your entire application set HTTP statuses on errors all over the place, is to define your own domain-specific error codes. For a small, web-only app, maybe HTTP status codes are sufficient, but in most real-world apps, they aren't.  Everything else about this pattern can still be used with your own domain-specific error codes.  Simply make your custom error types also return the appropriate HTTP (or JSON-RPC or gRPC or whatever...) codes as well. After such a change, our above database method might look more like:&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="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;db&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;DB&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;GetWidget&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;id&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="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Widget&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;widget&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;db&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="c"&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;errors&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Is&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;sql&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrNoRows&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;apperror&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ErrWidgetNotFound&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="n"&gt;widget&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;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Then the various callers can do their own error inspection, as appropriate:&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;internalCode&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;apperror&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="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// The internal error code&lt;/span&gt;

&lt;span class="n"&gt;httpStatus&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;apperror&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;HTTPStatus&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="c"&gt;// The HTTP status&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I leave the exact implementation of &lt;code&gt;apperror.ErrWidgetNotFound&lt;/code&gt; and the associated functions as an exercise for the reader.&lt;/p&gt;

&lt;h2&gt;
  
  
  Caveats
&lt;/h2&gt;

&lt;p&gt;This approach doesn't come without some drawbacks. It's worth calling a few of them out.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;It's non-standard.  Obviously. There's a cost in verbosity to be paid to convert from an error-returning handler to a standard handler.  Although it seems many people are happy to pay this cost, in the form of adopting a heavy framework that offers this benefit (along with others, of course).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;There are now &lt;em&gt;two&lt;/em&gt; ways to send responses to the client.  This annoys me.  But I have yet to find any way around it. And in practice, it doesn't seem to be a big problem, but it does require keeping it in mind.  You can set the HTTP status of a resonse &lt;em&gt;either&lt;/em&gt; by calling &lt;code&gt;w.WriteHeader()&lt;/code&gt;, &lt;em&gt;or&lt;/em&gt; by returning an error.  Each response can have only a single status, obviously.  And if you call &lt;code&gt;w.WriteHeader()&lt;/code&gt;, that one generally takes precident (unless you've implemented your own &lt;code&gt;http.ResponseWriter&lt;/code&gt; with different behavior).&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;It makes certain behaviors implicit. Or at least it can. As an example, the shown &lt;code&gt;apperr.HTTPStatus()&lt;/code&gt; function returns a default status for errors that don't contain a status. While I believe this makes good sense, and is a benefit, it is a bit "magical", and may surprise someone who's not familiar with the pattern at play.  It can also be confusing to see &lt;code&gt;apperr.WithStatus(err, http.StatusNotFound)&lt;/code&gt; the first time. While it should be apparent upon plain reading that it's including an HTTP status with an error, it's not apparent what other code consumes that status, or how its used.  Of course, the purpose of this post is to help solve this drawback.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;h2&gt;
  
  
  Other limitations
&lt;/h2&gt;

&lt;p&gt;This is by no means a one-size-fits-all solution.  A couple of obvious limitations I have run into on various applications:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;It doesn't provide any ergonomic way to specify a non-200, non-error status (such as 201). For this, you still must fall back on &lt;code&gt;w.WriteHeader()&lt;/code&gt;.&lt;/li&gt;
&lt;li&gt;Some applications would be better served with a function signature such as &lt;code&gt;func(*http.Request) (any, error)&lt;/code&gt;, such that a response (likely to be renderd as JSON) is the first return argument.&lt;/li&gt;
&lt;/ul&gt;

&lt;h2&gt;
  
  
  What's next?
&lt;/h2&gt;

&lt;p&gt;I mentioned at the outset that this pattern tends to lend itself to additional improvements. Let me just mention a few, without going into detail here.  If you'd like a longer explanation on any of these, &lt;a href="https://boldlygo.tech/contact"&gt;let me know&lt;/a&gt;.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Include additional metadata in errors. Stack traces are an obvious one, which is nicely provided by &lt;a href="https://pkg.go.dev/github.com/pkg/errors"&gt;&lt;code&gt;github.com/pkg/errors&lt;/code&gt;&lt;/a&gt;, for example. Expand your logging middleware to extract the stack trace and include it in logs.&lt;/li&gt;
&lt;li&gt;Hide error messages for certain HTTP statuses. I typically write my error-serving middleware to return simply &lt;code&gt;Internal Server Error&lt;/code&gt; to the client any time there's a 500 status, to avoid the risk of potentially reporting sensitive information, which can happen in some unsanitized errors. HTTP statuses 401 and 403 are also good candidates for this.&lt;/li&gt;
&lt;li&gt;Similar to obscuring certain errors, maybe you want to expose a user-friendly version of an error message to the users of your app, while logging the nitty gritty details that the error originally included. Add a &lt;code&gt;Public() string&lt;/code&gt; method to such errors, and send the &lt;code&gt;Public()&lt;/code&gt; version to your users, and the &lt;code&gt;Error()&lt;/code&gt; version to your logs.&lt;/li&gt;
&lt;li&gt;HTTP statuses not detailed enough for you? Maybe you need to distinguish between &lt;code&gt;widget not found&lt;/code&gt; and &lt;code&gt;user not found&lt;/code&gt;? You can create your own internal error status/codes, for use internally, which resolve to a common HTTP status.&lt;/li&gt;
&lt;li&gt;Look for ways to DRY up your code. For example, from the handler example, consider moving the call to &lt;code&gt;r.ParseForm&lt;/code&gt; and &lt;code&gt;strconv.Atoi&lt;/code&gt; to a common function—or use a validation library such as &lt;a href="https://pkg.go.dev/github.com/go-playground/validator/v10"&gt;github.com/go-playground/validator/v10&lt;/a&gt; in place of &lt;code&gt;strconv&lt;/code&gt; calls—which returns an error with 400 status.  Then your handler can just pass that error through.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;What other use cases have you seen, or can you think of? &lt;a href="https://boldlygo.tech/contact"&gt;I'd love to hear from you&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Is there a better way?
&lt;/h2&gt;

&lt;p&gt;I don't know.&lt;/p&gt;

&lt;p&gt;I'm always on the lookout for a better way to do things.&lt;/p&gt;

&lt;p&gt;If you know of a better pattern, or even small ways I can improve on this pattern, please, let me know! I'd love to learn from you!&lt;/p&gt;




&lt;p&gt;Banner image by &lt;a href="https://www.flickr.com/photos/ian_munroe/3848413116"&gt;ian munroe&lt;/a&gt;, &lt;a href="https://creativecommons.org/licenses/by/2.0/"&gt;CC-BY-2.0&lt;/a&gt;&lt;/p&gt;

</description>
      <category>go</category>
      <category>rest</category>
    </item>
    <item>
      <title>I'm going back to school, Live</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Mon, 16 Oct 2023 12:31:50 +0000</pubDate>
      <link>https://forem.com/jhall/im-going-back-to-school-live-g2d</link>
      <guid>https://forem.com/jhall/im-going-back-to-school-live-g2d</guid>
      <description>&lt;p&gt;I’m going back to school. And you’re invited along.&lt;/p&gt;

&lt;p&gt;Specifically, I’m preparing to go through &lt;a href="https://www.boot.dev/"&gt;boot.dev&lt;/a&gt;’s online course, “Learn Web Servers”.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--_WxMK9dC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwoo9pypkoh0yrwq7m76.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--_WxMK9dC--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/cwoo9pypkoh0yrwq7m76.png" alt="Image description" width="800" height="195"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Boot.dev is building the smartest way to master backend development by tackling the hardest problem with e-learning: boredom. The platform uses tactics learned from modern game design to push ambitious students toward their goal: a career in backend development. Through hands-on lessons that balance theory with practice, and an active Discord community, students are prepared to tackle technical interviews and forge a successful programming career.&lt;/p&gt;

&lt;p&gt;It offers courses in Python, a wee bit of JavaScript, and most important, obviously… &lt;em&gt;Go!&lt;/em&gt;&lt;/p&gt;

&lt;p&gt;If you’re new to Go or web servers, this will be an easy introduction to the concepts, and a chance to ask questions as you watch me make mistakes.&lt;/p&gt;

&lt;p&gt;Save the link, and be sure to subscribe to the &lt;a href="https://www.youtube.com/@boldlygo"&gt;Boldly Go youtube channel&lt;/a&gt;. I'll be going live in just a half an hour!&lt;/p&gt;

&lt;p&gt;Or if you're reading this in the future, of course you can still watch the replay.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/kwQ5npugi8Y"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

&lt;p&gt;I hope to see you there!&lt;/p&gt;

</description>
      <category>go</category>
      <category>webdev</category>
      <category>backend</category>
      <category>backenddevelopment</category>
    </item>
    <item>
      <title>Resolving type parameter ambiguities</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Thu, 03 Aug 2023 07:41:38 +0000</pubDate>
      <link>https://forem.com/jhall/resolving-type-parameter-ambiguities-4bol</link>
      <guid>https://forem.com/jhall/resolving-type-parameter-ambiguities-4bol</guid>
      <description>&lt;p&gt;I stumbled upon a bit of a WTF in the &lt;a href="https://go.dev/ref/spec"&gt;Go Specification&lt;/a&gt;, while writing my &lt;a href="https://boldlygo.tech/daily/"&gt;daily Go email&lt;/a&gt; and had to dig in a bit to make sense of it:&lt;/p&gt;

&lt;blockquote&gt;
&lt;h4&gt;
  
  
  &lt;a href="https://go.dev/ref/spec#Type_parameter_declarations"&gt;Type parameter declarations&lt;/a&gt;
&lt;/h4&gt;

&lt;p&gt;…&lt;/p&gt;

&lt;p&gt;A parsing ambiguity arises when the type parameter list for a generic type declares a single type parameter P with a constraint C such that the text P C forms a valid expression:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type T[P *C] …
type T[P (C)] …
type T[P *C|Q] …
…
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--SN48glEE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bs7za8ydw04adpmwar0r.gif" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--SN48glEE--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_66%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/bs7za8ydw04adpmwar0r.gif" alt="Image description" width="498" height="403"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;If you’re up for it, I’ll try to break this thing down. If you’re not up for it, no worries. See you later! 👋😆&lt;/p&gt;

&lt;p&gt;Let’s consider the first example provided: &lt;code&gt;type T[P *C] …&lt;/code&gt;. How can this be ambiguous?&lt;/p&gt;

&lt;p&gt;Well, it looks like an array type declaration, where the array length is derrived from a constant expression, such as in this 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;const&lt;/span&gt; &lt;span class="n"&gt;P&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;3&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;4&lt;/span&gt;

&lt;span class="k"&gt;type&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;P&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;C&lt;/span&gt;&lt;span class="p"&gt;]&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="c"&gt;// T is of type [12]int&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Other expressions are possible, too, which is what leads to this possible ambiguity.&lt;/p&gt;

&lt;p&gt;So, we need a way to solve this WTF scenario, and Go gives us two of them…&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;In these rare cases, the type parameter list is indistinguishable from an expression and the type declaration is parsed as an array type declaration. To resolve the ambiguity, embed the constraint in an interface or use a trailing comma:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;type T[P interface{*C}] …
type T[P *C,] …
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;So either wrap your constraint in &lt;code&gt;interface{…}&lt;/code&gt;, or add a magical comma at the end. &lt;em&gt;Poof!&lt;/em&gt; problem solved.&lt;/p&gt;

&lt;p&gt;But still. WTF?!&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Building a Go linter from scratch</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Mon, 31 Jul 2023 08:47:50 +0000</pubDate>
      <link>https://forem.com/jhall/building-a-go-linter-from-scratch-454g</link>
      <guid>https://forem.com/jhall/building-a-go-linter-from-scratch-454g</guid>
      <description>&lt;p&gt;🤔 Ever wonder how linters work in Go? ❓&lt;/p&gt;

&lt;p&gt;In my latest video, I go through Denis Isaev's tutorial "Writing Useful go/analysis Linter", to learn how to build a linter myself to learn what's involved.  Follow along and see if you can learn something, too...&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ycU-GXL_ix4"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>The 10 best Go versions, ranked</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Thu, 27 Jul 2023 07:29:48 +0000</pubDate>
      <link>https://forem.com/jhall/the-10-best-go-versions-ranked-22gl</link>
      <guid>https://forem.com/jhall/the-10-best-go-versions-ranked-22gl</guid>
      <description>&lt;p&gt;Go 1.21 is just around the corner, which will be the 22nd major Go release to date. So I thought it would be a good time to look back on the best Go releases we've had to date.&lt;/p&gt;

&lt;p&gt;&lt;iframe width="710" height="399" src="https://www.youtube.com/embed/ay4nCpbOuko"&gt;
&lt;/iframe&gt;
&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Go Lexical elements: Rune literals pt 3</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Sun, 09 Jul 2023 06:00:00 +0000</pubDate>
      <link>https://forem.com/jhall/go-lexical-elements-rune-literals-pt-3-24o3</link>
      <guid>https://forem.com/jhall/go-lexical-elements-rune-literals-pt-3-24o3</guid>
      <description>&lt;p&gt;Let’s continue our disection of &lt;code&gt;rune&lt;/code&gt; literals. If you missed the parts, check them out from &lt;a href="https://dev.to/tinydevops/go-lexical-elements-rune-literals-pt-1-intro-to-unicode-dn"&gt;Friday&lt;/a&gt; when we discussed Unicode, and &lt;a href="https://dev.to/tinydevops/go-lexical-elements-rune-literals-pt-2-3dn7"&gt;yesterday&lt;/a&gt; when we discussed quoting single characters.&lt;/p&gt;

&lt;p&gt;Today we’re looking at the various escape sequences supported by the &lt;code&gt;rune&lt;/code&gt; literal syntax.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://go.dev/ref/spec#Rune_literals"&gt;Rune literals&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;Several backslash escapes allow arbitrary values to be encoded as ASCII text. There are four ways to represent the integer value as a numeric constant: &lt;code&gt;\x&lt;/code&gt; followed by exactly two hexadecimal digits; &lt;code&gt;\u&lt;/code&gt; followed by exactly four hexadecimal digits; &lt;code&gt;\U&lt;/code&gt; followed by exactly eight hexadecimal digits, and a plain backslash &lt;code&gt;\&lt;/code&gt; followed by exactly three octal digits. In each case the value of the literal is the value represented by the digits in the corresponding base.&lt;/p&gt;

&lt;p&gt;Although these representations all result in an integer, they have different valid ranges. Octal escapes must represent a value between 0 and 255 inclusive. Hexadecimal escapes satisfy this condition by construction. The escapes &lt;code&gt;\u&lt;/code&gt; and &lt;code&gt;\U&lt;/code&gt; represent Unicode code points so within them some values are illegal, in particular those above &lt;code&gt;0x10FFFF&lt;/code&gt; and surrogate halves.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Let’s take these one at a time.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;A single octal byte&lt;/strong&gt; — &lt;code&gt;\OOO&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;You'll probably never use this, so let's get it out of the way first. But it's allowed. You can specify a byte using octal notation. However, note that as described, this is limited to values 0-255 inclusive, which means you can create an invalid &lt;code&gt;rune&lt;/code&gt; representation this way:&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;x&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'\400'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// # 400 octal == 256 decimal&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Produces the following error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;  octal escape value 256 &amp;gt; 255
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;One, two, or four hexidecimal bytes&lt;/strong&gt; — &lt;code&gt;\xXX&lt;/code&gt;, &lt;code&gt;\uXXXX&lt;/code&gt;, &lt;code&gt;\UXXXXXXXX&lt;/code&gt;
&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;This allows you to a single byte with two hexidecimal digits, (&lt;code&gt;\xXX&lt;/code&gt;), two bytes with four digits (&lt;code&gt;\uXXXX&lt;/code&gt;), or the full 4 bytes of a &lt;code&gt;rune&lt;/code&gt; with eight hexidecimal digits (&lt;code&gt;\UXXXXXXXX&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;And finally, there are some special escape sequences supported for &lt;code&gt;rune&lt;/code&gt; literals:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;After a backslash, certain single-character escapes represent special values:&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;\a   U+0007 alert or bell
\b   U+0008 backspace
\f   U+000C form feed
\n   U+000A line feed or newline
\r   U+000D carriage return
\t   U+0009 horizontal tab
\v   U+000B vertical tab
\\   U+005C backslash
\'   U+0027 single quote  (valid escape only within rune literals)
\"   U+0022 double quote  (valid escape only within string literals)
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

&lt;p&gt;(That last one arguably doesn't belong here, as it's not valid in a &lt;code&gt;rune&lt;/code&gt; literal, but it's nice to know that it's explicitly excluded here.)&lt;/p&gt;

&lt;p&gt;Let's round out today's email with the rest of the &lt;code&gt;rune&lt;/code&gt; literal section, which is just the boring EBNF syntax, and some examples, which we don't need to discuss in any detail.&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;An unrecognized character following a backslash in a rune literal is illegal.&lt;/p&gt;


&lt;pre class="highlight plaintext"&gt;&lt;code&gt;rune_lit         = "'" ( unicode_value | byte_value ) "'" .
unicode_value    = unicode_char | little_u_value | big_u_value | escaped_char .
byte_value       = octal_byte_value | hex_byte_value .
octal_byte_value = `\` octal_digit octal_digit octal_digit .
hex_byte_value   = `\` "x" hex_digit hex_digit .
little_u_value   = `\` "u" hex_digit hex_digit hex_digit hex_digit .
big_u_value      = `\` "U" hex_digit hex_digit hex_digit hex_digit
                           hex_digit hex_digit hex_digit hex_digit .
escaped_char     = `\` ( "a" | "b" | "f" | "n" | "r" | "t" | "v" | `\` | "'" | `"` ) .
&lt;/code&gt;&lt;/pre&gt;



&lt;pre class="highlight plaintext"&gt;&lt;code&gt;'a'
'ä'
'本'
'\t'
'\000'
'\007'
'\377'
'\x07'
'\xff'
'\u12e4'
'\U00101234'
'\''         // rune literal containing single quote character
'aa'         // illegal: too many characters
'\k'         // illegal: k is not recognized after a backslash
'\xa'        // illegal: too few hexadecimal digits
'\0'         // illegal: too few octal digits
'\400'       // illegal: octal value over 255
'\uDFFF'     // illegal: surrogate half
'\U00110000' // illegal: invalid Unicode code point
&lt;/code&gt;&lt;/pre&gt;

&lt;/blockquote&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Go Lexical elements: Rune literals pt 2</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Sat, 08 Jul 2023 06:00:00 +0000</pubDate>
      <link>https://forem.com/jhall/go-lexical-elements-rune-literals-pt-2-3dn7</link>
      <guid>https://forem.com/jhall/go-lexical-elements-rune-literals-pt-2-3dn7</guid>
      <description>&lt;p&gt;I write a daily email about Go, and this is a repost from my series &lt;a href="https://go.dev/ref/spec"&gt;Exploring the Go Spec&lt;/a&gt;. You're invited to &lt;a href="https://boldlygo.tech/daily?utm_source=devto&amp;amp;utm_campaign=runes&amp;amp;utm_medium=blog"&gt;sign up&lt;/a&gt; and follow along.&lt;/p&gt;




&lt;p&gt;Let’s continue our exploration of rune literals, which began on Monday. In summary from &lt;a href="https://dev.to/tinydevops/go-lexical-elements-rune-literals-pt-1-intro-to-unicode-dn"&gt;yesterday&lt;/a&gt;, a rune in Go represents a Unicode code point. Continuing from there…&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://go.dev/ref/spec#Rune_literals"&gt;Rune literals&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A rune literal is expressed as one or more characters enclosed in single quotes, as in &lt;code&gt;'x'&lt;/code&gt; or &lt;code&gt;'\n'&lt;/code&gt;. Within the quotes, any character may appear except newline and unescaped single quote. A single quoted character represents the Unicode value of the character itself, while multi-character sequences beginning with a backslash encode values in various formats.&lt;/p&gt;

&lt;p&gt;The simplest form represents the single character within the quotes; since Go source text is Unicode characters encoded in UTF-8, multiple UTF-8-encoded bytes may represent a single integer value. For instance, the literal &lt;code&gt;'a'&lt;/code&gt; holds a single byte representing a literal &lt;code&gt;a&lt;/code&gt;, Unicode U+0061, value &lt;code&gt;0x61&lt;/code&gt;, while &lt;code&gt;'ä'&lt;/code&gt; holds two bytes (&lt;code&gt;0xc3 0xa4&lt;/code&gt;) representing a literal &lt;code&gt;a&lt;/code&gt;-dieresis, U+00E4, value &lt;code&gt;0xe4&lt;/code&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;There are a few things I want to call out about this section of the spec, that aren’t always obvious, or are easily forgotten. Especially if you’re not already very familiar with Unicode.&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;A &lt;code&gt;rune&lt;/code&gt; represents a single “character” (technically: unicode code point, see yesterday's discussion).&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;rune&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; a single byte. (In fact, &lt;code&gt;rune&lt;/code&gt; is an alias for &lt;code&gt;int32&lt;/code&gt;, so it’s actually 4 bytes)&lt;/li&gt;
&lt;li&gt;A &lt;code&gt;rune&lt;/code&gt; is &lt;em&gt;not&lt;/em&gt; necissarily a single visible character, as many visible characters are built by combining multiple codepoints.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;As pointed out in the spec, both &lt;code&gt;'a'&lt;/code&gt; and &lt;code&gt;'ä'&lt;/code&gt; are valid &lt;code&gt;rune&lt;/code&gt; literals. The first also corresponds to a single ASCII (or Unicode) byte: &lt;code&gt;0x61&lt;/code&gt;. The second corresponds to two UTF-8 bytes: &lt;code&gt;0xc3&lt;/code&gt;, &lt;code&gt;0xa4&lt;/code&gt;. So it’s immediately clear that a &lt;code&gt;rune&lt;/code&gt; may contain multiple bytes.&lt;/p&gt;

&lt;p&gt;But recall the example from yesterday as well: &lt;code&gt;'ў'&lt;/code&gt; is a valid rune literal, and represents two bytes: &lt;code&gt;0xd1&lt;/code&gt;, &lt;code&gt;0x9e&lt;/code&gt;. But in contrast, the visually identical &lt;code&gt;'ў'&lt;/code&gt; is not a valid &lt;code&gt;rune&lt;/code&gt; literal, because it contains two Unicode code points, each of two bytes: &lt;code&gt;у&lt;/code&gt; (&lt;code&gt;0xd1&lt;/code&gt;, &lt;code&gt;0x83&lt;/code&gt;) followed by the breve mark, &lt;code&gt;˘&lt;/code&gt;, (&lt;code&gt;0xcc&lt;/code&gt;, &lt;code&gt;0x86&lt;/code&gt;).&lt;/p&gt;

&lt;p&gt;As you might expect, this can be an easy place to get tripped up. What you see on the screen is quite frequently not the whole story. I know of no fool-proof way to solve this confusion. The best I know is to be aware that the confusion exists, so when you see an error along the lines of “more than one character in rune literal”, you know where to begin your search.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Go Lexical elements: Rune literals pt 1, Intro to Unicode</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Fri, 07 Jul 2023 14:12:36 +0000</pubDate>
      <link>https://forem.com/jhall/go-lexical-elements-rune-literals-pt-1-intro-to-unicode-dn</link>
      <guid>https://forem.com/jhall/go-lexical-elements-rune-literals-pt-1-intro-to-unicode-dn</guid>
      <description>&lt;p&gt;I write a daily email about Go, and this is a repost from my series &lt;a href="https://go.dev/ref/spec"&gt;Exploring the Go Spec&lt;/a&gt;. You're invited to &lt;a href="https://boldlygo.tech/daily?utm_source=devto&amp;amp;utm_campaign=runes&amp;amp;utm_medium=blog"&gt;sign up&lt;/a&gt; and follow along.&lt;/p&gt;




&lt;p&gt;Runes… Oh boy! This is one of bits of Go that shines for its elegant simplicity, but constantly trips up everyone (myself included). As such, I think this may be a 2-, or maybe even a 3-parter.&lt;/p&gt;

&lt;p&gt;Let’s get started.&lt;/p&gt;

&lt;blockquote&gt;
&lt;h2&gt;
  
  
  &lt;a href="https://go.dev/ref/spec#Rune_literals"&gt;Rune literals&lt;/a&gt;
&lt;/h2&gt;

&lt;p&gt;A rune literal represents a &lt;a href="https://go.dev/ref/spec#Constants"&gt;rune constant&lt;/a&gt;, an integer value identifying a Unicode code point.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;If you’re already familiar with Unicode, and have a strong understanding of what a “code point” is, you can probably skip this one. See you later! 👋&lt;/p&gt;

&lt;p&gt;If you’re not completely sure what a Unicode code point is, stick around… I’ll do my best to untangle this seemingly simple phrase.&lt;/p&gt;

&lt;p&gt;First off, what is Unicode? It’s emojis, right? Ehh. If that’s your understanding of Unicode, which would be completely understandable, if your career in software is relatively young, then you need a bit more context. I encourage you to read a bit about the history of why Unicode was invented, and the problems it was meant to solve. This PDF, &lt;a href="https://digitaltools.labcd.unipi.it/wp-content/uploads/2021/05/Introduction-to-Unicode.pdf"&gt;&lt;em&gt;Introduction to Unicode: History of Character Codes&lt;/em&gt;&lt;/a&gt; is a good starting point.&lt;/p&gt;

&lt;p&gt;But here are the highlights:&lt;/p&gt;

&lt;p&gt;Before Unocide, we had many different coding systems. The most popular was ASCII, the &lt;em&gt;American Standard Code for Information Interchange&lt;/em&gt;. But since not all of the world is American, this had obvious drawbacks. Different countries or languages would often have their own coding schemes, but this made it very difficult to share documents between regions.&lt;/p&gt;

&lt;p&gt;If I wrote a document using the Cyrillic alphabet, then sent it to my colleague in France, he would likely see a jumble of French letters in seemingly random order.&lt;/p&gt;

&lt;p&gt;So Unicode came along to &lt;em&gt;Unify&lt;/em&gt; all the codes.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--0QeAtHrL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owngnbb1dkeuf960lwqi.jpg" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--0QeAtHrL--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_800/https://dev-to-uploads.s3.amazonaws.com/uploads/articles/owngnbb1dkeuf960lwqi.jpg" alt="One Code to Rule them All" width="800" height="450"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Great. So now instead of 127 possible characters in &lt;a href="https://en.wikipedia.org/wiki/ASCII"&gt;ASCII&lt;/a&gt;, we have a virtually unlimited number of characters, right?&lt;/p&gt;

&lt;p&gt;Not so fast.&lt;/p&gt;

&lt;p&gt;While there’s room in Unicode for more than 1 million individual code points, most are not (yet) defined. But what’s more, Unicode is smarter than ASCII in a number of ways. It is possible to &lt;a href="https://en.wikipedia.org/wiki/Combining_character"&gt;combine&lt;/a&gt; Unicode code points to form a single physical character.&lt;/p&gt;

&lt;p&gt;For example, if you want to display the Cyrillic letter &lt;em&gt;ў&lt;/em&gt;, this can be done by combining the Cyrillic Y (&lt;em&gt;у&lt;/em&gt;) with the breve mark (&lt;em&gt;˘&lt;/em&gt;), to give you &lt;em&gt;ў&lt;/em&gt;. But while this looks like a single character, and in print terms it is, it’s actually &lt;em&gt;two&lt;/em&gt; Unicode codepoints. As such, this code won’t compile:&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;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="err"&gt;'&lt;/span&gt;&lt;span class="n"&gt;у&lt;/span&gt;&lt;span class="err"&gt;̆'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Because while it visually looks like we’re quoting a single character, that character is composed of two Unicode codepoints, and (as we’ll see in the next section), a rune literal must be a single Unicode codepoint.&lt;/p&gt;

&lt;p&gt;Now if that’s not confusing enough, this code &lt;em&gt;will&lt;/em&gt; compile:&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;x&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="kt"&gt;rune&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="sc"&gt;'ў'&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What’s the difference?&lt;/p&gt;

&lt;p&gt;Well, Unicode includes a number of precomposed characters. This is a nice convenience for languages that commonly use a large number of these types of diacritics. But it’s an incovenience for us programmers. Not only does it mean that of these two character representations, only one is a valid &lt;code&gt;rune&lt;/code&gt;, it also introduces certain headaches when trying to compare Unicode strings for equality, or when sorting, etc.&lt;/p&gt;

&lt;p&gt;A last note for today, especially for anyone very new to Unicode. This concept of combining characters to add diacritics and other markings to an existing letter is the same way that Unicode emojis are modified to change skin tone, gender, or other attributes.&lt;/p&gt;

&lt;p&gt;Unicode is pretty powerful. And confusing at times.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Guess-Driven Development</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Tue, 04 Jul 2023 00:00:00 +0000</pubDate>
      <link>https://forem.com/jhall/guess-driven-development-3him</link>
      <guid>https://forem.com/jhall/guess-driven-development-3him</guid>
      <description>&lt;p&gt;Have you ever seen a pull request with half a dozen, seemingly unrelated changes, all in the name of fixing a specific bug?&lt;/p&gt;

&lt;p&gt;The last time this happened to me, I requested clarification on the purpose of a number of the changes, suggested a couple small refactors, pointed out that a couple of the changes were unnecessary or even counter-productive…&lt;/p&gt;

&lt;p&gt;After a few back-and-forths, the PR went from about 40 lines changed to 2 lines changed. All the unrelated, unnecessary bits had been removed.&lt;/p&gt;

&lt;p&gt;This is the result of what I have come to call Guess-Driven Development.&lt;/p&gt;

&lt;p&gt;It happens when someone doesn’t really know what’s causing a bug, so they just start changing things, until the bug goes away. Then they commit their entire change set, without much thought.&lt;/p&gt;




&lt;p&gt;&lt;em&gt;If you enjoyed this message, &lt;a href="https://jhall.io/daily"&gt;subscribe&lt;/a&gt; to &lt;u&gt;The Daily Commit&lt;/u&gt; to get future messages to your inbox.&lt;/em&gt;&lt;/p&gt;

</description>
      <category>guessdrivendevelopme</category>
      <category>antipatterns</category>
      <category>pullrequests</category>
    </item>
    <item>
      <title>Go Constants can't overflow</title>
      <dc:creator>Jonathan Hall</dc:creator>
      <pubDate>Fri, 23 Jun 2023 12:50:04 +0000</pubDate>
      <link>https://forem.com/jhall/go-constants-cant-overflow-4c0h</link>
      <guid>https://forem.com/jhall/go-constants-cant-overflow-4c0h</guid>
      <description>&lt;p&gt;Did you know that constants in Go can't overflow?&lt;/p&gt;

&lt;p&gt;Quoting the &lt;a href="https://go.dev/ref/spec#Constants"&gt;Go spec&lt;/a&gt;:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Numeric constants represent exact values of arbitrary precision and do not overflow. Consequently, there are no constants denoting the IEEE-754 negative zero, infinity, and not-a-number values.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;Now this is a very interesting thing about constants in Go, and it’s something that confuses a lot of people. So let’s play around with this one a bit.&lt;/p&gt;

&lt;p&gt;If you’re experienced with compiled languages, you’re probably already familiar with numeric overflows. Each language handles this differently, but in general, you can’t store more than 8 bits of data in an 8-bit variable.&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;x&lt;/span&gt; &lt;span class="kt"&gt;int8&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;256&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;will predictably complain:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;256 (untyped int constant) overflows int8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;But notice the parenthetical note in that error message: “untyped int constant”&lt;/p&gt;

&lt;p&gt;We’ll talk more about untyped constants soon, but for now the interesting thing to point out is that it’s not the constant expression (i.e. &lt;code&gt;256&lt;/code&gt;) that overflowed. It’s the variable assignment (i.e. &lt;code&gt;x +=&lt;/code&gt;) that overflowed.&lt;/p&gt;

&lt;p&gt;This is because, as quoted from the spec above, constants &lt;em&gt;do not overflow&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;You can create constant expressions in Go of arbitrary precision, and they’re valid. Check this out:&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;x&lt;/span&gt; &lt;span class="kt"&gt;int8&lt;/span&gt;
&lt;span class="n"&gt;x&lt;/span&gt; &lt;span class="o"&gt;+=&lt;/span&gt; &lt;span class="m"&gt;2560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;It still produces essentially the same error:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;2560000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 (untyped int constant) overflows int8
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;That value is effectively a 312-bit integer (if my math isn’t off). There’s no data type in Go that can store a 312-bit integer. So you might expect that constant to overflow. But it doesn’t. Because constants &lt;em&gt;do not overflow&lt;/em&gt;.&lt;/p&gt;

&lt;p&gt;But as soon as you try to assign a constant to a variable, that &lt;em&gt;assignment&lt;/em&gt; may cause an overflow.&lt;/p&gt;

&lt;p&gt;Jumping ahead a bit to the end of this section in the spec, we see a note on implementation requirements:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Implementation restriction: Although numeric constants have arbitrary precision in the language, a compiler may implement them using an internal representation with limited precision. That said, every implementation must:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Represent integer constants with at least 256 bits.
-Represent floating-point constants, including the parts of a complex constant, with a mantissa of at least 256 bits and a signed binary exponent of at least 16 bits.&lt;/li&gt;
&lt;li&gt;Give an error if unable to represent an integer constant precisely.&lt;/li&gt;
&lt;li&gt;Give an error if unable to represent a floating-point or complex constant due to overflow.&lt;/li&gt;
&lt;li&gt;Round to the nearest representable constant if unable to represent a floating-point or complex constant due to limits on precision.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;These requirements apply both to literal constants and to the result of evaluating &lt;a href="https://go.dev/ref/spec#Constant_expressions"&gt;constant expressions&lt;/a&gt;.&lt;/p&gt;
&lt;/blockquote&gt;

&lt;p&gt;So there’s a bit of a caveat to this “constants do not overflow” rule. An implementation may choose to round a constant representations to 256 bits, for example. So my 312-bit example above may be rounded to &lt;code&gt;2559999999999999972095373170245681839337968901451475214262959301931782193648482834514033246208&lt;/code&gt; in such an implementation (again: if my math isn’t off).&lt;/p&gt;

&lt;p&gt;So if you want to be super-paranoid, limit your constant literals to 256 bits of precision. 😉&lt;/p&gt;




&lt;p&gt;If you learned something reading this, you'll learn something every day by subscribing to my daily Go mailing list! Sign up for &lt;a href="https://boldlygo.tech/daily"&gt;Boldly Go: Daily&lt;/a&gt;.&lt;/p&gt;

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