<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:content="http://purl.org/rss/1.0/modules/content/">
  <channel>
    <title>Golang on Haseeb Majid</title>
    <link>https://haseebmajid.dev/tags/golang/</link>
    <description>Recent content in Golang on Haseeb Majid</description>
    <generator>Hugo -- gohugo.io</generator>
    <language>en</language>
    <lastBuildDate>Thu, 16 Nov 2023 00:00:00 +0000</lastBuildDate><atom:link href="https://haseebmajid.dev/tags/golang/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>TIL: How to Debug a Test in Golang With Build Tags in Neovim</title>
      <link>https://haseebmajid.dev/posts/2023-11-16-til-how-to-debug-a-test-in-golang-with-build-tags-in-neovim/</link>
      <pubDate>Thu, 16 Nov 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-11-16-til-how-to-debug-a-test-in-golang-with-build-tags-in-neovim/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Debug a Test in Golang With Build Tags in Neovim&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;I was having issues with my debugger today (well technically yesterday because I am publishing this a day later to spread
out my blog posts but same difference) and it took me a few hours to realise what was going on. In my case, I was
trying to debug a test written in Golang using &lt;code&gt;nvim-dap-go&lt;/code&gt; on Neovim.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Debug a Test in Golang With Build Tags in Neovim</strong></p>
<p>I was having issues with my debugger today (well technically yesterday because I am publishing this a day later to spread
out my blog posts but same difference) and it took me a few hours to realise what was going on. In my case, I was
trying to debug a test written in Golang using <code>nvim-dap-go</code> on Neovim.</p>
<p>The reason the test was failing  because the test file had build tags so delve (the debugger) couldn&rsquo;t compile
the file, i.e. using the unit build tag in the example below.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="c1">//go:build unit
</span></span></span><span class="line"><span class="cl"><span class="c1">// +build unit
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">options_test</span>
</span></span></code></pre></div><p>When we set up the <code>dag-go</code> plugin, we need to pass an extra field called <code>build_flags</code>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">lua</span> <span class="n">require</span><span class="p">(</span><span class="s1">&#39;dap-go&#39;</span><span class="p">).</span><span class="n">setup</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">delve</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl">    <span class="n">build_flags</span> <span class="o">=</span> <span class="s2">&#34;-tags=unit,integration,e2e&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Replace the above with the tags you use! If you are using NixVim you should be able to do something like this <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="n">programs</span><span class="o">.</span><span class="n">nixvim</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">plugins</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">dap</span><span class="o">.</span><span class="n">extensions</span><span class="o">.</span><span class="n">dap-go</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="n">enable</span> <span class="o">=</span> <span class="no">true</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="n">delve</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="n">path</span> <span class="o">=</span> <span class="s2">&#34;</span><span class="si">${</span><span class="n">pkgs</span><span class="o">.</span><span class="n">delve</span><span class="si">}</span><span class="s2">/bin/dlv&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">          <span class="n">buildFlags</span> <span class="o">=</span> <span class="s2">&#34;-tags=unit,integration,e2e&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">        <span class="p">};</span>
</span></span><span class="line"><span class="cl">      <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">  <span class="p">};</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Then I have a keybinding to debug the nearest test like so, again using NixVim.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-nix" data-lang="nix"><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="n">action</span> <span class="o">=</span> <span class="s2">&#34;&lt;cmd&gt; lua require(&#39;dap-go&#39;).debug_test()&lt;CR&gt;&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">key</span> <span class="o">=</span> <span class="s2">&#34;&lt;leader&gt;td&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="n">options</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Debug Nearest (Go)&#34;</span><span class="p">;</span>
</span></span><span class="line"><span class="cl">    <span class="p">};</span>
</span></span><span class="line"><span class="cl">    <span class="n">mode</span> <span class="o">=</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="s2">&#34;n&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">];</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span></code></pre></div><p>in lua:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">vim.keymap</span><span class="p">.</span><span class="n">set</span><span class="p">(</span><span class="s2">&#34;n&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;leader&gt;td&#34;</span><span class="p">,</span> <span class="s2">&#34;&lt;cmd&gt;lua require(&#39;dap-go&#39;).debug_test()&lt;CR&gt;&#34;</span><span class="p">)</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>After this PR is merged, <a href="https://github.com/nix-community/nixvim/pull/703">https://github.com/nix-community/nixvim/pull/703</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Disable Linters in Golangci Lint for Test Files</title>
      <link>https://haseebmajid.dev/posts/2023-10-10-til-how-to-disable-linters-in-golangci-lint-for-test-files/</link>
      <pubDate>Tue, 10 Oct 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-10-10-til-how-to-disable-linters-in-golangci-lint-for-test-files/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Disable Linters in Golangci Lint for Test Files&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Today (for once), I ran &lt;code&gt;golangci-lint run&lt;/code&gt; and it failed on CI with the following error:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-bash&#34; data-lang=&#34;bash&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;internal/options/parser_test.go:13: Function &lt;span class=&#34;s1&#34;&gt;&amp;#39;TestParse&amp;#39;&lt;/span&gt; is too long &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;m&#34;&gt;69&lt;/span&gt; &amp;gt; 60&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;funlen&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;func TestParse&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;t *testing.T&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt; &lt;span class=&#34;o&#34;&gt;{&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;task: Failed to run task &lt;span class=&#34;s2&#34;&gt;&amp;#34;lint&amp;#34;&lt;/span&gt;: &lt;span class=&#34;nb&#34;&gt;exit&lt;/span&gt; status &lt;span class=&#34;m&#34;&gt;1&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Where my &lt;code&gt;.golangci.yml&lt;/code&gt; file looked like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;nt&#34;&gt;run&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;timeout&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;l&#34;&gt;5m&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;skip-dirs&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;direnv&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;&lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;linters&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;  &lt;/span&gt;&lt;span class=&#34;nt&#34;&gt;enable&lt;/span&gt;&lt;span class=&#34;p&#34;&gt;:&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;bodyclose&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;dogsled&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;dupl&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;errcheck&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;exportloopref&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;funlen&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gochecknoinits&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;goconst&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gocritic&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gocyclo&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gofmt&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;goimports&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gomnd&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;goprintffuncname&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gosec&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;gosimple&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;govet&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;ineffassign&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;lll&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;misspell&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;nakedret&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;noctx&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;nolintlint&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;revive&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;staticcheck&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;stylecheck&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;typecheck&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;unconvert&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;unparam&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;unused&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;w&#34;&gt;    &lt;/span&gt;- &lt;span class=&#34;l&#34;&gt;whitespace&lt;/span&gt;&lt;span class=&#34;w&#34;&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;So basically we want the ability to turn off &lt;code&gt;funlen&lt;/code&gt; for our tests (and other linters). Because we don&amp;rsquo;t mind
if some of our test functions get a big long with different sub-tests.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Disable Linters in Golangci Lint for Test Files</strong></p>
<p>Today (for once), I ran <code>golangci-lint run</code> and it failed on CI with the following error:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">internal/options/parser_test.go:13: Function <span class="s1">&#39;TestParse&#39;</span> is too long <span class="o">(</span><span class="m">69</span> &gt; 60<span class="o">)</span> <span class="o">(</span>funlen<span class="o">)</span>
</span></span><span class="line"><span class="cl">func TestParse<span class="o">(</span>t *testing.T<span class="o">)</span> <span class="o">{</span>
</span></span><span class="line"><span class="cl">task: Failed to run task <span class="s2">&#34;lint&#34;</span>: <span class="nb">exit</span> status <span class="m">1</span>
</span></span></code></pre></div><p>Where my <code>.golangci.yml</code> file looked like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">run</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">timeout</span><span class="p">:</span><span class="w"> </span><span class="l">5m</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">skip-dirs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">direnv</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">linters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">enable</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">bodyclose</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">dogsled</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">dupl</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">errcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">exportloopref</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">funlen</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gochecknoinits</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">goconst</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gocritic</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gocyclo</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gofmt</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">goimports</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gomnd</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">goprintffuncname</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gosec</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">gosimple</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">govet</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">ineffassign</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">lll</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">misspell</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">nakedret</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">noctx</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">nolintlint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">revive</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">staticcheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">stylecheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">typecheck</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">unconvert</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">unparam</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">unused</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">whitespace</span><span class="w">
</span></span></span></code></pre></div><p>So basically we want the ability to turn off <code>funlen</code> for our tests (and other linters). Because we don&rsquo;t mind
if some of our test functions get a big long with different sub-tests.</p>
<p>So to disable some linters for our test files we can do something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-yaml" data-lang="yaml"><span class="line"><span class="cl"><span class="nt">linters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">  </span><span class="nt">enable</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span>- <span class="l">bodyclose</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">    </span><span class="c"># ...</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w"></span><span class="nt">issues</span><span class="p">:</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w">  </span><span class="nt">exclude-rules</span><span class="p">:</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w">    </span>- <span class="nt">path</span><span class="p">:</span><span class="w"> </span><span class="l">_test.go</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w">      </span><span class="nt">linters</span><span class="p">:</span><span class="w">
</span></span></span><span class="line hl"><span class="cl"><span class="w">        </span>- <span class="l">funlen</span><span class="w">
</span></span></span></code></pre></div><p>That&rsquo;s it! For once a TIL, that was written on the same day as I learned it (or re-learnt it)</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to Use Neotest Dap With Lazyvim for Golang Development</title>
      <link>https://haseebmajid.dev/posts/2023-07-31-how-to-use-neotest-dap-with-lazyvim-for-golang-development/</link>
      <pubDate>Mon, 31 Jul 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-07-31-how-to-use-neotest-dap-with-lazyvim-for-golang-development/</guid>
      <description>&lt;p&gt;In this blog post, I will show you how you can easily setup Neotest to make testing easier in neovim and DAP to make
debugging your tests is a lot easier.&lt;/p&gt;
&lt;p&gt;I am using the &lt;a href=&#34;https://www.lazyvim.org/&#34;&gt;LazyVim&lt;/a&gt; neovim distribution, where these two come as easily installed extra
plugins. However, it should be easy enough for you to copy the config over to your neovim lua config.
LazyVim even has the config available on its website, you don&amp;rsquo;t even need to deep dive into the code &amp;#x1f604;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>In this blog post, I will show you how you can easily setup Neotest to make testing easier in neovim and DAP to make
debugging your tests is a lot easier.</p>
<p>I am using the <a href="https://www.lazyvim.org/">LazyVim</a> neovim distribution, where these two come as easily installed extra
plugins. However, it should be easy enough for you to copy the config over to your neovim lua config.
LazyVim even has the config available on its website, you don&rsquo;t even need to deep dive into the code &#x1f604;.</p>
<p>For example with <a href="https://www.lazyvim.org/extras/dap/core">dap</a>. Here are some examples of what it can look like. The two
main bits we will look at today don&rsquo;t come by default with LazyVim but are &ldquo;extras&rdquo; we can add them</p>
<h2 id="neotest">Neotest</h2>
<p>To set up Neotest on LazyVim, go to your LazyVim <a href="https://github.com/LazyVim/starter">starter repo</a>. Then open our
<code>lazy.lua</code> file and add the following lines:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">spec</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">-- add LazyVim and import its plugins</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;LazyVim/LazyVim&#34;</span><span class="p">,</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;lazyvim.plugins&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">-- import any extras modules here</span>
</span></span><span class="line hl"><span class="cl">    <span class="p">{</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;lazyvim.plugins.extras.test.core&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;lazyvim.plugins.extras.lang.go&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">-- import/override with your plugins</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;plugins&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span></code></pre></div><p>Here you can see the output from a test at the bottom (from Neotest) and a test summary (on the right).
Using the test summary we can easily run one test at a time, even subtests.</p>
<p><img
        loading="lazy"
        src="/posts/2023-07-31-how-to-use-neotest-dap-with-lazyvim-for-golang-development/images/test_summary.png"
        type=""
        alt="Test Summary"
        
      /></p>
<p>The config that LazyVim sets the following key binds.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">keys</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;tt&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">run.run</span><span class="p">(</span><span class="n">vim.fn</span><span class="p">.</span><span class="n">expand</span><span class="p">(</span><span class="s2">&#34;%&#34;</span><span class="p">))</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Run File&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;tT&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">run.run</span><span class="p">(</span><span class="n">vim.loop</span><span class="p">.</span><span class="n">cwd</span><span class="p">())</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Run All Test Files&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;tr&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">run.run</span><span class="p">()</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Run Nearest&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;ts&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">summary.toggle</span><span class="p">()</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Toggle Summary&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;to&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">output.open</span><span class="p">({</span> <span class="n">enter</span> <span class="o">=</span> <span class="kc">true</span><span class="p">,</span> <span class="n">auto_close</span> <span class="o">=</span> <span class="kc">true</span> <span class="p">})</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Show Output&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;tO&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">output_panel.toggle</span><span class="p">()</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Toggle Output Panel&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;&lt;leader&gt;tS&#34;</span><span class="p">,</span> <span class="kr">function</span><span class="p">()</span> <span class="n">require</span><span class="p">(</span><span class="s2">&#34;neotest&#34;</span><span class="p">).</span><span class="n">run.stop</span><span class="p">()</span> <span class="kr">end</span><span class="p">,</span> <span class="n">desc</span> <span class="o">=</span> <span class="s2">&#34;Stop&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span></code></pre></div><p>So we can get the test summary by pressing <code>&lt;space&gt; + t + s</code>.
Or test output using <code>&lt;space&gt; + t + shift + o</code>. Where <code>&lt;space&gt;</code> is my leader key. Also if a test fails when I run
the nearest test <code>&lt;space&gt; + t + n</code>, the output panel (at the bottom) auto opens.</p>
<h2 id="dap-core">DAP Core</h2>
<p>Similar to above to add debugging support we can add an extra plugin like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-lua" data-lang="lua"><span class="line"><span class="cl"><span class="n">spec</span> <span class="o">=</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="c1">-- add LazyVim and import its plugins</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="s2">&#34;LazyVim/LazyVim&#34;</span><span class="p">,</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;lazyvim.plugins&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">-- import any extras modules here</span>
</span></span><span class="line hl"><span class="cl">    <span class="p">{</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;lazyvim.plugins.extras.dap.core&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl">    <span class="c1">-- import/override with your plugins</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span> <span class="n">import</span> <span class="o">=</span> <span class="s2">&#34;plugins&#34;</span> <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">},</span>
</span></span></code></pre></div><p><img
        loading="lazy"
        src="/posts/2023-07-31-how-to-use-neotest-dap-with-lazyvim-for-golang-development/images/test_debug.png"
        type=""
        alt="Test Debug"
        
      /></p>
<p>To debug our tests first we can add a breakpoint using <code>&lt;space&gt; + d + b</code>. Then we can run our test in debug mode using
<code>&lt;space&gt; + t + d</code>, which will run the nearest test in <a href="https://github.com/LazyVim/LazyVim/blob/566049aa4a26a86219dd1ad1624f9a1bf18831b6/lua/lazyvim/plugins/extras/lang/go.lua#L20">debug mode</a>.</p>
<p>When we start to debug our tests it looks something like this. If you have used the VSCode debugger this will look very
similar. We can explore the current state, the values various variables have etc. Run commands in the debugger at the
bottom.</p>
<p>That&rsquo;s it! We can improve our testing experience in Go using neovim with Neotest and DAP. I am also able to replicate
some features I used to have in VSCode and now also have in neovim 💗.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://www.youtube.com/watch?v=7Nt8n3rjfDY">This video helping me get set up by Elijah Manor (he does great videos btw)</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Set a Relationship on Golang Pocketbase</title>
      <link>https://haseebmajid.dev/posts/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-/</link>
      <pubDate>Wed, 08 Mar 2023 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Set a Relationship on Golang Pocketbase&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;a href=&#34;https://pocketbase.io/&#34;&gt;Pocketbase&lt;/a&gt; is a backend as a service, it is very nice because it is written in Golang
it can compile down to a single binary. It also allows us to extend it using Golang and use it as a framework.
In my case, I needed some extra logic before adding data to the database so I decided to extend Pocketbase
and write some of my business logic.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Set a Relationship on Golang Pocketbase</strong></p>
<p><a href="https://pocketbase.io/">Pocketbase</a> is a backend as a service, it is very nice because it is written in Golang
it can compile down to a single binary. It also allows us to extend it using Golang and use it as a framework.
In my case, I needed some extra logic before adding data to the database so I decided to extend Pocketbase
and write some of my business logic.</p>
<p>Part of the code involved adding some entries to the Database including a relationship. However, I noticed that the relationship
looked different in the Pocketbase GUI as compared with the ones I created using the Pocketbase client in the SvelteKit part of my app.</p>
<p>The other relationships showed up a bit differently, they didn&rsquo;t include the id of the relationship (as a foreign key) but rather a field
on the other collection. In the example below the relationship field I am referencing is the <code>bookmark_metadata</code>. Which uses the <code>title</code> field.</p>
<p><img
        loading="lazy"
        src="/posts/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-/images/bookmark.png"
        type=""
        alt="Bookmark"
        
      /></p>
<p>Where the bookmark metadata may look like:</p>
<p><img
        loading="lazy"
        src="/posts/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-/images/bookmark_metadata.png"
        type=""
        alt="Bookmark Metadata"
        
      /></p>
<p>We can achieve this using the following code:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="nx">bookmarkRecord</span> <span class="o">:=</span> <span class="nx">models</span><span class="p">.</span><span class="nf">NewRecord</span><span class="p">(</span><span class="nx">collection</span><span class="p">)</span>
</span></span><span class="line hl"><span class="cl"><span class="nx">bookmarkRecord</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;bookmark_metadata&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span><span class="nx">metadataRecord</span><span class="p">.</span><span class="nx">Id</span><span class="p">})</span>
</span></span><span class="line"><span class="cl"><span class="nx">bookmarkRecord</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;favourite&#34;</span><span class="p">,</span> <span class="kc">false</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">bookmarkRecord</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;collection&#34;</span><span class="p">,</span> <span class="nx">collectionID</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">bookmarkRecord</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;custom_order&#34;</span><span class="p">,</span> <span class="nx">math</span><span class="p">.</span><span class="nx">MaxInt32</span><span class="p">)</span>
</span></span></code></pre></div><p>The key being that we set <code>bookmark_metadata</code> as a slice (array).
However, if we did:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="nx">bookmarkRecord</span><span class="p">.</span><span class="nf">Set</span><span class="p">(</span><span class="s">&#34;bookmark_metadata&#34;</span><span class="p">,</span> <span class="nx">metadataRecord</span><span class="p">.</span><span class="nx">Id</span><span class="p">)</span>
</span></span></code></pre></div><p>In the GUI the record would look like this:</p>
<p><img
        loading="lazy"
        src="/posts/2023-03-08--til-how-to-set-a-relationship-on-golang-pocketbase-/images/bookmark_id.png"
        type=""
        alt="Bookmark ID"
        
      /></p>
<p>Both options will work for setting up a relationship between two collections. I just wanted to show you how you can set it
so it shows up like relationship created via the JS SDK. You can read more about creating records with Golang
<a href="https://pocketbase.io/docs/record-methods/#create-new-record">here</a>.</p>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How To Add Custom Syntax Highlighting Rules in VS Code</title>
      <link>https://haseebmajid.dev/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/</link>
      <pubDate>Tue, 27 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How To Add Custom Syntax Highlighting Rules in VS Code&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;The other day (a few months ago) I was comparing Goland and VS Code for Golang development.
I noticed Goland by default seemed to have nicer syntax highlighting, so I started looking at
what I could do in VS Code to do this.&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;Before&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img
        loading=&#34;lazy&#34;
        src=&#34;https://haseebmajid.dev/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/images/before.png&#34;
        type=&#34;&#34;
        alt=&#34;Before&#34;
        
      /&gt;&lt;/p&gt;
&lt;blockquote&gt;
&lt;p&gt;After&lt;/p&gt;
&lt;/blockquote&gt;
&lt;p&gt;&lt;img
        loading=&#34;lazy&#34;
        src=&#34;https://haseebmajid.dev/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/images/after.png&#34;
        type=&#34;&#34;
        alt=&#34;After&#34;
        
      /&gt;&lt;/p&gt;
&lt;p&gt;It turns out we can do this with our own custom rules using &lt;code&gt;editor.tokenColorCustomizations&lt;/code&gt;.
To do this go to our settings (&lt;code&gt;settings.json&lt;/code&gt;) and add something like:&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How To Add Custom Syntax Highlighting Rules in VS Code</strong></p>
<p>The other day (a few months ago) I was comparing Goland and VS Code for Golang development.
I noticed Goland by default seemed to have nicer syntax highlighting, so I started looking at
what I could do in VS Code to do this.</p>
<blockquote>
<p>Before</p>
</blockquote>
<p><img
        loading="lazy"
        src="/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/images/before.png"
        type=""
        alt="Before"
        
      /></p>
<blockquote>
<p>After</p>
</blockquote>
<p><img
        loading="lazy"
        src="/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/images/after.png"
        type=""
        alt="After"
        
      /></p>
<p>It turns out we can do this with our own custom rules using <code>editor.tokenColorCustomizations</code>.
To do this go to our settings (<code>settings.json</code>) and add something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;editor.tokenColorCustomizations&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;[Dracula]&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;textMateRules&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;scope&#34;</span><span class="p">:</span> <span class="s2">&#34;source.go&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;settings&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">            <span class="nt">&#34;foreground&#34;</span><span class="p">:</span> <span class="s2">&#34;#6dd8ce&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">}</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where:</p>
<ul>
<li><code>Dracula</code> is the colour scheme</li>
<li><code>scope</code> is the type of token we want to colour</li>
</ul>
<p>We can find out what we should set the scope as by going to the command palette and selecting <code>Developer: Inspect Editor Tokens and Scopes</code>.</p>
<p><img
        loading="lazy"
        src="/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/images/command.png"
        type=""
        alt="Command Palette"
        
      /></p>
<p>Then go and hover over the different parts of our code and it will tell you what type of token it is <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p><img
        loading="lazy"
        src="/posts/2022-12-27-til-how-to-add-custom-syntax-highlighting-rules-in-vs-code/images/token.png"
        type=""
        alt="Token"
        
      /></p>
<p>That&rsquo;s it!</p>
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p><a href="https://blog.4d.com/setting-up-code-syntax-highlighting-using-the-visual-studio-code-extension/">https://blog.4d.com/setting-up-code-syntax-highlighting-using-the-visual-studio-code-extension/</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Use Prettier with Hugo/Golang Templates</title>
      <link>https://haseebmajid.dev/posts/2022-12-12-til-how-to-use-prettier-with-hugo-golang-templates/</link>
      <pubDate>Mon, 12 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2022-12-12-til-how-to-use-prettier-with-hugo-golang-templates/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Use Prettier with Hugo/Golang Templates&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;If you try to use prettier on a (Hugo) Golang HTML template you may get something that looks like this:&lt;/p&gt;
&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; class=&#34;chroma&#34;&gt;&lt;code class=&#34;language-go-html-template&#34; data-lang=&#34;go-html-template&#34;&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;or&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;na&#34;&gt;.Params.author&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;site&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;.Params.author&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;.Params.author&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;|&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;default&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;site&lt;/span&gt;&lt;span class=&#34;na&#34;&gt;.Params.author&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author_type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;:=&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;printf&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;%T&amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;if&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;or&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;eq&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author_type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;[]string&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;k&#34;&gt;eq&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author_type&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;[]interface {}&amp;#34;&lt;/span&gt;&lt;span class=&#34;o&#34;&gt;))&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;(&lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;delimit&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;s&#34;&gt;&amp;#34;, &amp;#34;&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;o&#34;&gt;)&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;else&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;    &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;nx&#34;&gt;$author&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;  &lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;span class=&#34;line&#34;&gt;&lt;span class=&#34;cl&#34;&gt;&lt;span class=&#34;cp&#34;&gt;{{-&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;k&#34;&gt;end&lt;/span&gt;&lt;span class=&#34;w&#34;&gt; &lt;/span&gt;&lt;span class=&#34;cp&#34;&gt;-}}&lt;/span&gt;
&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;into this&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Use Prettier with Hugo/Golang Templates</strong></p>
<p>If you try to use prettier on a (Hugo) Golang HTML template you may get something that looks like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go-html-template" data-lang="go-html-template"><span class="line"><span class="cl"><span class="cp">{{-</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="na">.Params.author</span><span class="w"> </span><span class="nx">site</span><span class="na">.Params.author</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="cp">{{-</span><span class="w"> </span><span class="nx">$author</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">(</span><span class="na">.Params.author</span><span class="w"> </span><span class="o">|</span><span class="w"> </span><span class="nx">default</span><span class="w"> </span><span class="nx">site</span><span class="na">.Params.author</span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="cp">{{-</span><span class="w"> </span><span class="nx">$author_type</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">(</span><span class="k">printf</span><span class="w"> </span><span class="s">&#34;%T&#34;</span><span class="w"> </span><span class="nx">$author</span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="cp">{{-</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="o">(</span><span class="k">or</span><span class="w"> </span><span class="o">(</span><span class="k">eq</span><span class="w"> </span><span class="nx">$author_type</span><span class="w"> </span><span class="s">&#34;[]string&#34;</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="k">eq</span><span class="w"> </span><span class="nx">$author_type</span><span class="w"> </span><span class="s">&#34;[]interface {}&#34;</span><span class="o">))</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">    <span class="cp">{{-</span><span class="w"> </span><span class="o">(</span><span class="nx">delimit</span><span class="w"> </span><span class="nx">$author</span><span class="w"> </span><span class="s">&#34;, &#34;</span><span class="w"> </span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="cp">{{-</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">    <span class="cp">{{-</span><span class="w"> </span><span class="nx">$author</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl">  <span class="cp">{{-</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">}}</span>
</span></span><span class="line"><span class="cl"><span class="cp">{{-</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">-}}</span>
</span></span></code></pre></div><p>into this</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go-html-template" data-lang="go-html-template"><span class="line"><span class="cl"><span class="cp">{{-</span><span class="w"> </span><span class="k">if</span><span class="w"> </span><span class="k">or</span><span class="w"> </span><span class="na">.Params.author</span><span class="w"> </span><span class="nx">site</span><span class="na">.Params.author</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w"> </span><span class="nx">$author</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">(</span><span class="na">.Params.author</span><span class="w"> </span><span class="o">|</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nx">default</span><span class="w"> </span><span class="nx">site</span><span class="na">.Params.author</span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w"> </span><span class="nx">$author_type</span><span class="w"> </span><span class="o">:=</span><span class="w"> </span><span class="o">(</span><span class="k">printf</span><span class="w"> </span><span class="s">&#34;%T&#34;</span><span class="w"> </span><span class="nx">$author</span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="k">if</span><span class="w"> </span><span class="o">(</span><span class="k">or</span><span class="w"> </span><span class="o">(</span><span class="k">eq</span><span class="w"> </span><span class="nx">$author_type</span><span class="w"> </span><span class="s">&#34;[]string&#34;</span><span class="o">)</span><span class="w"> </span><span class="o">(</span><span class="k">eq</span><span class="w"> </span><span class="nx">$author_type</span><span class="w"> </span><span class="s">&#34;[]interface {}&#34;</span><span class="o">))</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="o">(</span><span class="nx">delimit</span><span class="w"> </span><span class="nx">$author</span><span class="w"> </span><span class="s">&#34;, &#34;</span><span class="w"> </span><span class="o">)</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w"> </span><span class="k">else</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w"> </span><span class="nx">$author</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">}}</span> <span class="cp">{{-</span><span class="w"> </span><span class="k">end</span><span class="w"> </span><span class="cp">-}}</span>
</span></span></code></pre></div><p>This of course something we don&rsquo;t want. So let&rsquo;s use a prettier plugin that can solve this problem for us.
Let us install <code>npm install --save-dev prettier-plugin-go-template</code>.</p>
<p>Create a <code>.prettierrc</code> file with the following contents:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;overrides&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">    <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;files&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;*.html&#34;</span><span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;options&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;parser&#34;</span><span class="p">:</span> <span class="s2">&#34;go-template&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">}</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;goTemplateBracketSpacing&#34;</span><span class="p">:</span> <span class="kc">true</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Prettier will now format our HTML files correctly, in our Hugo project.</p>
<h2 id="optional-settings">Optional Settings</h2>
<p>By default the format of our files like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span>
</span></span><span class="line"><span class="cl">  <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://github.com/reorx/hugo-PaperModX/&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="na">rel</span><span class="o">=</span><span class="s">&#34;noopener&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="na">target</span><span class="o">=</span><span class="s">&#34;_blank&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">&gt;&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>If we add the following option to the <code>.prettierrc</code>, <code>&quot;bracketSameLine&quot;: true</code> then our file will look like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">a</span>
</span></span><span class="line"><span class="cl">  <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://github.com/reorx/hugo-PaperModX/&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="na">rel</span><span class="o">=</span><span class="s">&#34;noopener&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="na">target</span><span class="o">=</span><span class="s">&#34;_blank&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">&gt;&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>Sometimes our file may look something like this:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  Analytics by
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://{{ .Site.Params.goatcounter }}.goatcounter.com&#34;</span>
</span></span><span class="line"><span class="cl">    <span class="p">&gt;</span>Goatcounter.<span class="p">&lt;/</span><span class="nt">a</span>
</span></span><span class="line"><span class="cl">  <span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span></code></pre></div><p>To fix the dangling <code>&gt;</code> we can add the following option to the <code>.prettierrc</code> file ,  <code>&quot;htmlWhitespaceSensitivity&quot;: &quot;ignore&quot;</code> then our
file will look like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-html" data-lang="html"><span class="line"><span class="cl"><span class="p">&lt;</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">  Analytics by
</span></span><span class="line"><span class="cl">  <span class="p">&lt;</span><span class="nt">a</span> <span class="na">href</span><span class="o">=</span><span class="s">&#34;https://{{ .Site.Params.goatcounter }}.goatcounter.com&#34;</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl">    Goatcounter.
</span></span><span class="line"><span class="cl">  <span class="p">&lt;/</span><span class="nt">a</span><span class="p">&gt;</span>
</span></span><span class="line"><span class="cl"><span class="p">&lt;/</span><span class="nt">span</span><span class="p">&gt;</span>
</span></span></code></pre></div>]]></content:encoded>
    </item>
    
    <item>
      <title>TIL: How to Separate our Golang Tests</title>
      <link>https://haseebmajid.dev/posts/2022-12-04-til-how-to-separate-our-golang-tests/</link>
      <pubDate>Sun, 04 Dec 2022 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2022-12-04-til-how-to-separate-our-golang-tests/</guid>
      <description>&lt;p&gt;&lt;strong&gt;TIL: How to Separate our Golang Tests&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;Sometimes we want to be able to run our unit tests and integration tests separately.
In Golang we can do this using build tags, build tags are used to tell the compiler
important information when we run &lt;code&gt;go build&lt;/code&gt; &lt;sup id=&#34;fnref:1&#34;&gt;&lt;a href=&#34;#fn:1&#34; class=&#34;footnote-ref&#34; role=&#34;doc-noteref&#34;&gt;1&lt;/a&gt;&lt;/sup&gt;.&lt;/p&gt;
&lt;p&gt;Let say we have a file called &lt;code&gt;package_test.go&lt;/code&gt;. By adding &lt;code&gt;// +build integration&lt;/code&gt; to the top of the file
without any whitespace. This test file will only be run when we specify the tags in our
test command &lt;code&gt;go test --tags=integration&lt;/code&gt;.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p><strong>TIL: How to Separate our Golang Tests</strong></p>
<p>Sometimes we want to be able to run our unit tests and integration tests separately.
In Golang we can do this using build tags, build tags are used to tell the compiler
important information when we run <code>go build</code> <sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>.</p>
<p>Let say we have a file called <code>package_test.go</code>. By adding <code>// +build integration</code> to the top of the file
without any whitespace. This test file will only be run when we specify the tags in our
test command <code>go test --tags=integration</code>.</p>
<p>Our integration test file would look something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-golang" data-lang="golang"><span class="line"><span class="cl"><span class="c1">// +build integration
</span></span></span><span class="line"><span class="cl"><span class="c1"></span>
</span></span><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">mypackage_test</span>
</span></span></code></pre></div><p>Our unit tests can be left without any build tags and can be run with <code>go test</code> like normal.</p>
<p>To get this to compile correctly with VS Code we need to add the following to <code>settings.json</code> file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">{</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;go.buildFlags&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">      <span class="s2">&#34;-tags=integration&#34;</span>
</span></span><span class="line"><span class="cl">  <span class="p">],</span>
</span></span><span class="line"><span class="cl">  <span class="nt">&#34;go.testTags&#34;</span><span class="p">:</span> <span class="s2">&#34;integration&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>More about Golang build tags, <a href="https://mickey.dev/posts/go-build-tags-testing/">https://mickey.dev/posts/go-build-tags-testing/</a>&#160;<a href="#fnref:1" class="footnote-backref" role="doc-backlink">&#x21a9;&#xfe0e;</a></p>
</li>
</ol>
</div>
]]></content:encoded>
    </item>
    
    <item>
      <title>How to create a Golang Web Application using Fizz</title>
      <link>https://haseebmajid.dev/posts/2021-01-19-how-to-create-a-golang-web-application-using-fizz/</link>
      <pubDate>Tue, 19 Jan 2021 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2021-01-19-how-to-create-a-golang-web-application-using-fizz/</guid>
      <description>&lt;h1 id=&#34;background&#34;&gt;Background&lt;/h1&gt;
&lt;p&gt;A bit of background before we start the article. When I develop a Python web service I use the
&lt;a href=&#34;https://github.com/zalando/connexion&#34;&gt;Connexion library created by Zalando&lt;/a&gt;. It&amp;rsquo;s a great library which is built on top of
Flask. It uses an OpenAPI Specification (OAS) file to handle input validation and routing for you. Therefore reducing the boilerplate code you need to write.&lt;/p&gt;
&lt;p&gt;The main advantage of this is that we have a design-first approach to developing our API. We fully define the
OAS then develop the code/web service. This also keeps the OAS up to date, helping to mitigate the issue of the
code/documentation getting out of date. Especially when you share the OAS with other people (clients) to use. The last
thing you want to do is give them an out-of-date file.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<h1 id="background">Background</h1>
<p>A bit of background before we start the article. When I develop a Python web service I use the
<a href="https://github.com/zalando/connexion">Connexion library created by Zalando</a>. It&rsquo;s a great library which is built on top of
Flask. It uses an OpenAPI Specification (OAS) file to handle input validation and routing for you. Therefore reducing the boilerplate code you need to write.</p>
<p>The main advantage of this is that we have a design-first approach to developing our API. We fully define the
OAS then develop the code/web service. This also keeps the OAS up to date, helping to mitigate the issue of the
code/documentation getting out of date. Especially when you share the OAS with other people (clients) to use. The last
thing you want to do is give them an out-of-date file.</p>
<p>Anyways short story aside, recently I started learning Golang and developing a simple CRUD web service using Gin.
However, I discovered (at least at the time of writing) there was no equivalent library to Connexion. The closest
library I could find was Fizz.</p>
<h2 id="what-is-fizz">What is Fizz?</h2>
<p>Fizz almost works the opposite way Connexion does. It generates an OAS
file from our code. Now again I prefer the Connexion approach because we just use
the OAS file we created at the beginning of the project. However, this is the next best thing.</p>
<p>What I ended up doing was creating an OAS by hand. Then implementing that OAS using Golang and letting Fizz
auto-generate the &ldquo;new&rdquo; OAS. This &ldquo;new&rdquo; OAS is the one that gets shared with clients and is kept up to date.
In theory the OAS I defined manually can now be deleted as it&rsquo;s not required anymore.</p>
<p>This solves the problem of our code getting out-of-date with the specification.
Fizz also uses other libraries behind the scenes to help us reduce the boilerplate code similiar to
how Connexion works.</p>
<h1 id="web-service">Web Service</h1>
<p>Now onto the real meat and potatoes of this article. We will create three different endpoints:</p>
<ul>
<li>GET /healthcheck: Checks if the application is healthy or not</li>
<li>GET /pet/{name}: Get information about a single pet</li>
<li>PUT /pet/{name}: Update information about a single pet</li>
</ul>
<h2 id="structure">Structure</h2>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"></code></pre></div><p>Our project will follow the structure shown above. We will go (no pun intended 🤷) over what each of the folder &ldquo;do&rdquo;.</p>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">Core Code</summary>
  
  <p>Since this example application is so simple we don&rsquo;t have a <code>core</code> folder but for more complicated
applications you should probably add another folder inline with the <code>server</code> folder. For example, this could include code that interacts with the database.</p>
<p>This helps to de-couple the application&rsquo;s various layers. You could, for example, remove the web service part in the <code>server</code> folder and
turn into a CLI application at a later date. Using the core code you already have.</p>

</details>

<h2 id="dependencies">Dependencies</h2>
<p>The main dependency for this project is <a href="https://github.com/wI2L/fizz">Fizz</a>. Simply run <code>go get github.com/wI2L/fizz</code> to
install it.</p>
<h2 id="internal">internal</h2>
<p>The main logic of our web service will be stored within the <code>internal</code> folder.</p>
<h3 id="server">server</h3>
<p>This folder contains all the logic related to the web service itself. This will include
models (data structure returned to the client) and the controllers, which are functions
that will handle the various requests sent by clients. They act as an &ldquo;interface&rdquo; to our application.</p>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">Fizz Routing</summary>
  
  The Fizz library abstracts away routing partially for us, more on this later.
</details>

<h4 id="models">models</h4>
<p>This folder contains all the data structure and data types that will be received by the application
from the client or sent back to the client from the application. For example:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">models</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">Pet</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Name</span>  <span class="kt">string</span> <span class="s">`json:&#34;name&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Price</span> <span class="kt">int</span>    <span class="s">`json:&#34;price&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Breed</span> <span class="kt">string</span> <span class="s">`json:&#34;breed&#34;`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This will be the object sent back to the client when they request to get a pet. Note the use of struct tags
<code>json:&quot;name&quot;</code>. When the data is unmarshaled from JSON to this struct (again we will see how this done later) the <code>Name</code>
field will look for the <code>name</code> field in the JSON file. Later on we will see why we need to specify struct tags and not
just us being explicit.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">models</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">PetParams</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Name</span> <span class="kt">string</span> <span class="s">`query:&#34;name&#34;`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Note the struct tag in this example is <code>query</code> and not <code>json</code> because it&rsquo;s used as a query parameter.
We also have one final type of model to take a look at:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">models</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="c1">// PetsInput is the body data and params combined into a single struct.
</span></span></span><span class="line"><span class="cl"><span class="c1"></span><span class="kd">type</span> <span class="nx">PetInput</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">PetParams</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Pet</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This model is used when we need to pass both a Pet struct in the body of a request and also a query parameter. Again
we will see exactly how we use this model a bit later.</p>
<h4 id="controllers">controllers</h4>
<p>The controllers folder contains the main web service logic for the application. It contains the one function for every
route/endpoint you have in your application. Let&rsquo;s take a look at the maintenance controller first</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">controllers</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;net&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;time&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/gin-gonic/gin&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/juju/errors&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="s">&#34;gitlab.com/hmajid2301/articles/example-fizz-project/internal/server/models&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">Healthcheck</span><span class="p">(</span><span class="nx">_</span> <span class="o">*</span><span class="nx">gin</span><span class="p">.</span><span class="nx">Context</span><span class="p">)</span> <span class="p">(</span><span class="o">*</span><span class="nx">models</span><span class="p">.</span><span class="nx">Healthcheck</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">host</span> <span class="o">:=</span> <span class="s">&#34;example.com&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="nx">port</span> <span class="o">:=</span> <span class="s">&#34;80&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="nx">timeout</span> <span class="o">:=</span> <span class="nx">time</span><span class="p">.</span><span class="nf">Duration</span><span class="p">(</span><span class="mi">1</span> <span class="o">*</span> <span class="nx">time</span><span class="p">.</span><span class="nx">Second</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="nx">_</span><span class="p">,</span> <span class="nx">healthy</span> <span class="o">:=</span> <span class="nx">net</span><span class="p">.</span><span class="nf">DialTimeout</span><span class="p">(</span><span class="s">&#34;tcp&#34;</span><span class="p">,</span> <span class="nx">host</span><span class="o">+</span><span class="s">&#34;:&#34;</span><span class="o">+</span><span class="nx">port</span><span class="p">,</span> <span class="nx">timeout</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">healthy</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="o">&amp;</span><span class="nx">models</span><span class="p">.</span><span class="nx">Healthcheck</span><span class="p">{},</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;Healthcheck Failed!&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="o">&amp;</span><span class="nx">models</span><span class="p">.</span><span class="nx">Healthcheck</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Message</span><span class="p">:</span> <span class="s">&#34;The API is healthy.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>So we have defined a new function, which receives a single argument the gin context (which we don&rsquo;t use, hence the <code>_</code>).
This function returns the health check model. It simply checks if we can connect to
<code>example.com:80</code> (on port 80).</p>
<p>Fizz uses the <a href="https://github.com/loopfz/gadgeto/tree/master/tonic">Tonic library</a> to assign function handlers to our
route.</p>
<blockquote>
<p>Package tonic handles path/query/body parameter binding in a single consolidated input object which allows you to remove all the boilerplate code that retrieves and tests the presence of various parameters. - Tonic README</p>
</blockquote>
<p>We need to specify two return types in the function definition because this function is a handler set using Tonic
Again we will see how we do this in the <code>routes.go</code> file. The first return type is a struct, which will be
returned to the client (marshalled into JSON). In the example above this is the <code>*models.Healthcheck</code>.
The second is an <code>error</code>, again we will see how errors are handled a bit later.</p>
<p>Let&rsquo;s now take a look at the pets controller.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">controllers</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/gin-gonic/gin&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;github.com/juju/errors&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;gitlab.com/hmajid2301/articles/example-fizz-project/internal/server/models&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">GetPet</span><span class="p">(</span><span class="nx">_</span> <span class="o">*</span><span class="nx">gin</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">params</span> <span class="o">*</span><span class="nx">models</span><span class="p">.</span><span class="nx">PetParams</span><span class="p">)</span> <span class="p">(</span><span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">params</span><span class="p">.</span><span class="nx">Name</span> <span class="o">!=</span> <span class="s">&#34;bob&#34;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">{},</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">NotFoundf</span><span class="p">(</span><span class="s">&#34;Pet %s&#34;</span><span class="p">,</span> <span class="nx">params</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Name</span><span class="p">:</span>  <span class="s">&#34;bob&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Price</span><span class="p">:</span> <span class="mi">100</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Breed</span><span class="p">:</span> <span class="s">&#34;bengal&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">UpdatePet</span><span class="p">(</span><span class="nx">_</span> <span class="o">*</span><span class="nx">gin</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">input</span> <span class="o">*</span><span class="nx">models</span><span class="p">.</span><span class="nx">PetInput</span><span class="p">)</span> <span class="p">(</span><span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">input</span><span class="p">.</span><span class="nx">PetParams</span><span class="p">.</span><span class="nx">Name</span> <span class="o">!=</span> <span class="s">&#34;bob&#34;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">{},</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">NotFoundf</span><span class="p">(</span><span class="s">&#34;Pet %s&#34;</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">PetParams</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">input</span><span class="p">.</span><span class="nx">Pet</span><span class="p">,</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>The first function:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">GetPet</span><span class="p">(</span><span class="nx">_</span> <span class="o">*</span><span class="nx">gin</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">params</span> <span class="o">*</span><span class="nx">models</span><span class="p">.</span><span class="nx">PetParams</span><span class="p">)</span> <span class="p">(</span><span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">params</span><span class="p">.</span><span class="nx">Name</span> <span class="o">!=</span> <span class="s">&#34;bob&#34;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">{},</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">NotFoundf</span><span class="p">(</span><span class="s">&#34;Pet %s&#34;</span><span class="p">,</span> <span class="nx">params</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Name</span><span class="p">:</span>  <span class="s">&#34;bob&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Price</span><span class="p">:</span> <span class="mi">100</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Breed</span><span class="p">:</span> <span class="s">&#34;bengal&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><details
  class="notice info"
  open="true"
>
    <summary class="notice-title">JuJu Errors</summary>
  
  For throwing errors in this application we used <a href="https://github.com/juju/errors">juju&rsquo;s error library</a>.
</details>

<p>The main difference in this function is we pass in an extra parameter which is the query parameter <code>{name}</code>. The logic of this function is not very smart because
it expects the name of the pet to be <code>bob</code> in order to send a successful respone back to the client. Of course in
reality you would look in your data store for information about the pet.</p>
<p>The second function looks like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">UpdatePet</span><span class="p">(</span><span class="nx">_</span> <span class="o">*</span><span class="nx">gin</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">input</span> <span class="o">*</span><span class="nx">models</span><span class="p">.</span><span class="nx">PetInput</span><span class="p">)</span> <span class="p">(</span><span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">input</span><span class="p">.</span><span class="nx">PetParams</span><span class="p">.</span><span class="nx">Name</span> <span class="o">!=</span> <span class="s">&#34;bob&#34;</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">models</span><span class="p">.</span><span class="nx">Pet</span><span class="p">{},</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">NotFoundf</span><span class="p">(</span><span class="s">&#34;Pet %s&#34;</span><span class="p">,</span> <span class="nx">input</span><span class="p">.</span><span class="nx">PetParams</span><span class="p">.</span><span class="nx">Name</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">input</span><span class="p">.</span><span class="nx">Pet</span><span class="p">,</span> <span class="kc">nil</span>
</span></span></code></pre></div><p>Again this is slightly different because the client sends both a HTTP body and a path query parameter. So the
<code>input</code> argument is a combination of two structs:</p>
<p>We can access the query parameter like so <code>input.PetParams.Name</code> and the pet&rsquo;s data like <code>input.Pet</code>. Note how we
use the name of the struct after <code>input</code>. This is how we can combine the body, query parameters and also the query
string into a single struct. The struct tags are really important as they let Tonic know what type of data that field is
i.e. <code>json</code> or <code>query</code> etc.</p>
<p>Again we can ignore the logic of the function itself. It&rsquo;s not supposed to be very complicated. Just more of an
example of how we can use Fizz, with more complicated HTTP requests.</p>
<h4 id="routesgo">routes.go</h4>
<p>This file is where we link the routes to their specific handler functions (using Tonic). This is also where we
provide most of the data that will be used to populate the OAS file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">NewRouter</span><span class="p">()</span> <span class="p">(</span><span class="o">*</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">Fizz</span><span class="p">,</span> <span class="kt">error</span><span class="p">)</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">engine</span> <span class="o">:=</span> <span class="nx">gin</span><span class="p">.</span><span class="nf">New</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">engine</span><span class="p">.</span><span class="nf">Use</span><span class="p">(</span><span class="nx">cors</span><span class="p">.</span><span class="nf">Default</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">fizzApp</span> <span class="o">:=</span> <span class="nx">fizz</span><span class="p">.</span><span class="nf">NewFromEngine</span><span class="p">(</span><span class="nx">engine</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">infos</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">openapi</span><span class="p">.</span><span class="nx">Info</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Title</span><span class="p">:</span>       <span class="s">&#34;Example API&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Description</span><span class="p">:</span> <span class="s">&#34;The API definition for the Example API.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Version</span><span class="p">:</span>     <span class="s">&#34;1.0.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">fizzApp</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/openapi.json&#34;</span><span class="p">,</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fizzApp</span><span class="p">.</span><span class="nf">OpenAPI</span><span class="p">(</span><span class="nx">infos</span><span class="p">,</span> <span class="s">&#34;json&#34;</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">group</span> <span class="o">:=</span> <span class="nx">fizzApp</span><span class="p">.</span><span class="nf">Group</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;maintenance&#34;</span><span class="p">,</span> <span class="s">&#34;Related to managing the maintenance of the API.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/healthcheck&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Checks API is healthy.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">Healthcheck</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/pets:name&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Get a pet by name.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusNotFound</span><span class="p">),</span> <span class="s">&#34;Pet Not Found&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">GetPet</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">PUT</span><span class="p">(</span><span class="s">&#34;/pets:name&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Update a pet.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">UpdatePet</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">fizzApp</span><span class="p">.</span><span class="nf">Errors</span><span class="p">())</span> <span class="o">!=</span> <span class="mi">0</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;fizz errors: %v&#34;</span><span class="p">,</span> <span class="nx">fizzApp</span><span class="p">.</span><span class="nf">Errors</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="nx">tonic</span><span class="p">.</span><span class="nf">SetErrorHook</span><span class="p">(</span><span class="nx">errHook</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">fizzApp</span><span class="p">,</span> <span class="kc">nil</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Let&rsquo;s break this function down:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="nx">engine</span> <span class="o">:=</span> <span class="nx">gin</span><span class="p">.</span><span class="nf">New</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">engine</span><span class="p">.</span><span class="nf">Use</span><span class="p">(</span><span class="nx">cors</span><span class="p">.</span><span class="nf">Default</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">fizzApp</span> <span class="o">:=</span> <span class="nx">fizz</span><span class="p">.</span><span class="nf">NewFromEngine</span><span class="p">(</span><span class="nx">engine</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">infos</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">openapi</span><span class="p">.</span><span class="nx">Info</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Title</span><span class="p">:</span>       <span class="s">&#34;Example API&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Description</span><span class="p">:</span> <span class="s">&#34;The API definition for the Example API.&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Version</span><span class="p">:</span>     <span class="s">&#34;1.0.0&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">fizzApp</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/openapi.json&#34;</span><span class="p">,</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fizzApp</span><span class="p">.</span><span class="nf">OpenAPI</span><span class="p">(</span><span class="nx">infos</span><span class="p">,</span> <span class="s">&#34;json&#34;</span><span class="p">)</span>
</span></span></code></pre></div><p>First, we create the Gin engine and share this with a new Fizz engine. Fizz just uses Gin behind the scenes.
Then we create an info struct, which stores the metadata for the generated OAS file. Then we add a new route
<code>/openapi.json</code>, which will serve the OAS file.</p>
<p>Note we could change the path if we wanted and serve
a YAML file as well <code>fizzApp.GET(&quot;/openapi&quot;, nil, fizzApp.OpenAPI(infos, &quot;yaml&quot;))</code>. Here we removed the
extension and changed the generated file so that we will serve the client a YAML file.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="nx">group</span> <span class="o">:=</span> <span class="nx">fizzApp</span><span class="p">.</span><span class="nf">Group</span><span class="p">(</span><span class="s">&#34;&#34;</span><span class="p">,</span> <span class="s">&#34;endpoints&#34;</span><span class="p">,</span> <span class="s">&#34;All of the endpoints.&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/healthcheck&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Checks API is healthy.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">Healthcheck</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/pets:name&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Get a pet by name.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusNotFound</span><span class="p">),</span> <span class="s">&#34;Pet Not Found&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">GetPet</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">PUT</span><span class="p">(</span><span class="s">&#34;/pets:name&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Update a pet.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">UpdatePet</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span></code></pre></div><p>Next, let&rsquo;s get to the part of the function where we define our routes. First, we create a group, this will group the
routes within the OAS (such as the tag).</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="nx">group</span><span class="p">.</span><span class="nf">GET</span><span class="p">(</span><span class="s">&#34;/pets:name&#34;</span><span class="p">,</span> <span class="p">[]</span><span class="nx">fizz</span><span class="p">.</span><span class="nx">OperationOption</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Summary</span><span class="p">(</span><span class="s">&#34;Get a pet by name.&#34;</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">),</span> <span class="s">&#34;Server Error&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">		<span class="nx">fizz</span><span class="p">.</span><span class="nf">Response</span><span class="p">(</span><span class="nx">fmt</span><span class="p">.</span><span class="nf">Sprint</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusNotFound</span><span class="p">),</span> <span class="s">&#34;Pet Not Found&#34;</span><span class="p">,</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{},</span> <span class="kc">nil</span><span class="p">,</span> <span class="kc">nil</span><span class="p">),</span>
</span></span><span class="line"><span class="cl">	<span class="p">},</span> <span class="nx">tonic</span><span class="p">.</span><span class="nf">Handler</span><span class="p">(</span><span class="nx">controllers</span><span class="p">.</span><span class="nx">GetPet</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusOK</span><span class="p">))</span>
</span></span></code></pre></div><p>Next, let&rsquo;s take a look at how we define a new route. We add it to our existing group, then we give it some
information to add to the OAS such as summary. What responses we can get here I have defined the possible
errors. Note that because I prefer not to use magic numbers I have used the <code>http</code> package constants instead
of using numbers i.e. 404 -&gt; <code>http.StatusNotFound</code>. And of course the most important bit, the Tonic handler
where we tell this route what function to call when a client sends a request to this route. In this case, we
choose the <code>GetPet</code> function we mentioned earlier and on a successful response we return a <code>200</code> status code i.e.
<code>http.StatusOK</code>.</p>
<p>You can define whichever status code you want here such as an <code>http.StatusCreated</code> or <code>http.NoContent</code>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="k">if</span> <span class="nb">len</span><span class="p">(</span><span class="nx">fizzApp</span><span class="p">.</span><span class="nf">Errors</span><span class="p">())</span> <span class="o">!=</span> <span class="mi">0</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="kc">nil</span><span class="p">,</span> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;fizz errors: %v&#34;</span><span class="p">,</span> <span class="nx">fizzApp</span><span class="p">.</span><span class="nf">Errors</span><span class="p">())</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="nx">tonic</span><span class="p">.</span><span class="nf">SetErrorHook</span><span class="p">(</span><span class="nx">errHook</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">fizzApp</span><span class="p">,</span> <span class="kc">nil</span>
</span></span></code></pre></div><p>The final part of the function checks if Fizz returned any errors and sets up the Tonic error hook. What to do if
any of the Tonic function handler return an error. As we saw earlier with some of the functions
returning errors.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">errHook</span><span class="p">(</span><span class="nx">_</span> <span class="o">*</span><span class="nx">gin</span><span class="p">.</span><span class="nx">Context</span><span class="p">,</span> <span class="nx">e</span> <span class="kt">error</span><span class="p">)</span> <span class="p">(</span><span class="kt">int</span><span class="p">,</span> <span class="kd">interface</span><span class="p">{})</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="o">:=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">,</span> <span class="nx">http</span><span class="p">.</span><span class="nf">StatusText</span><span class="p">(</span><span class="nx">http</span><span class="p">.</span><span class="nx">StatusInternalServerError</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">ok</span> <span class="o">:=</span> <span class="nx">e</span><span class="p">.(</span><span class="nx">tonic</span><span class="p">.</span><span class="nx">BindError</span><span class="p">);</span> <span class="nx">ok</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusBadRequest</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span> <span class="k">else</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">switch</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsBadRequest</span><span class="p">(</span><span class="nx">e</span><span class="p">),</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsNotValid</span><span class="p">(</span><span class="nx">e</span><span class="p">),</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsNotSupported</span><span class="p">(</span><span class="nx">e</span><span class="p">),</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsNotProvisioned</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusBadRequest</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsForbidden</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusForbidden</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsMethodNotAllowed</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusMethodNotAllowed</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsNotFound</span><span class="p">(</span><span class="nx">e</span><span class="p">),</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsUserNotFound</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusNotFound</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsUnauthorized</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusUnauthorized</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsAlreadyExists</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusConflict</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="k">case</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">IsNotImplemented</span><span class="p">(</span><span class="nx">e</span><span class="p">):</span>
</span></span><span class="line"><span class="cl">			<span class="nx">code</span><span class="p">,</span> <span class="nx">msg</span> <span class="p">=</span> <span class="nx">http</span><span class="p">.</span><span class="nx">StatusNotImplemented</span><span class="p">,</span> <span class="nx">e</span><span class="p">.</span><span class="nf">Error</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">		<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="o">:=</span> <span class="nx">models</span><span class="p">.</span><span class="nx">APIError</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Message</span><span class="p">:</span> <span class="nx">msg</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">code</span><span class="p">,</span> <span class="nx">err</span>
</span></span></code></pre></div><p>This function receives an error since we are using juju error in our controller functions. We can then use the <code>isX</code>
the function provided by the library to check what kind of error we received. Using a switch statement we then determine
what type of HTTP status code to return to the client depending on the error thrown by the function. For example an <code>NotFoundError</code> means we return <code>http.StatusNotFound</code> (404).</p>
<p>Ok, that&rsquo;s the main part of our application so how do we start our web service?</p>
<h2 id="cmd">cmd</h2>
<p>In our cmd folder, we have the <code>main.go</code> file.</p>
<h3 id="maingo">main.go</h3>
<p>The <code>main.go</code> file, as is good practice in Golang, is used to start our application.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kn">package</span> <span class="nx">main</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kn">import</span> <span class="p">(</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;log&#34;</span>
</span></span><span class="line"><span class="cl">	<span class="s">&#34;net/http&#34;</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="s">&#34;gitlab.com/hmajid2301/articles/example-fizz-project/internal/server&#34;</span>
</span></span><span class="line"><span class="cl"><span class="p">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">func</span> <span class="nf">main</span><span class="p">()</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">router</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">server</span><span class="p">.</span><span class="nf">NewRouter</span><span class="p">()</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">log</span><span class="p">.</span><span class="nf">Fatal</span><span class="p">(</span><span class="nx">err</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="nx">srv</span> <span class="o">:=</span> <span class="o">&amp;</span><span class="nx">http</span><span class="p">.</span><span class="nx">Server</span><span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Addr</span><span class="p">:</span>    <span class="s">&#34;:8080&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Handler</span><span class="p">:</span> <span class="nx">router</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">	<span class="nx">srv</span><span class="p">.</span><span class="nf">ListenAndServe</span><span class="p">()</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>In the root folder of our application run this command <code>go run cmd/example-fizz-project/main.go</code>. Then you should see something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-bash" data-lang="bash"><span class="line"><span class="cl">go run cmd/example-fizz-project/main.go
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>GIN-debug<span class="o">]</span> <span class="o">[</span>WARNING<span class="o">]</span> Running in <span class="s2">&#34;debug&#34;</span> mode. Switch to <span class="s2">&#34;release&#34;</span> mode in production.
</span></span><span class="line"><span class="cl"> - using env:   <span class="nb">export</span> <span class="nv">GIN_MODE</span><span class="o">=</span>release
</span></span><span class="line"><span class="cl"> - using code:  gin.SetMode<span class="o">(</span>gin.ReleaseMode<span class="o">)</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="o">[</span>GIN-debug<span class="o">]</span> GET    /openapi.json             --&gt; github.com/wI2L/fizz.<span class="o">(</span>*Fizz<span class="o">)</span>.OpenAPI.func1 <span class="o">(</span><span class="m">2</span> handlers<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>GIN-debug<span class="o">]</span> GET    /healthcheck              --&gt; github.com/wI2L/fizz.<span class="o">(</span>*RouterGroup<span class="o">)</span>.Handle.func1 <span class="o">(</span><span class="m">2</span> handlers<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>GIN-debug<span class="o">]</span> GET    /pets:name                --&gt; github.com/wI2L/fizz.<span class="o">(</span>*RouterGroup<span class="o">)</span>.Handle.func1 <span class="o">(</span><span class="m">2</span> handlers<span class="o">)</span>
</span></span><span class="line"><span class="cl"><span class="o">[</span>GIN-debug<span class="o">]</span> PUT    /pets:name                --&gt; github.com/wI2L/fizz.<span class="o">(</span>*RouterGroup<span class="o">)</span>.Handle.func1 <span class="o">(</span><span class="m">2</span> handlers<span class="o">)</span>
</span></span></code></pre></div><p>And voila you now have a working web service you have created using Fizz. That&rsquo;s it we have now built a web application with Fizz and Golang.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://gitlab.com/hmajid2301/blog/-/tree/main/content/posts/2021-01-19-how-to-create-a-golang-web-application-using-fizz/source_code">Example source code</a></li>
<li><a href="https://github.com/wI2L/fizz/">Fizz</a></li>
<li><a href="https://github.com/loopfz/gadgeto/tree/master/tonic">Tonic</a></li>
<li><a href="https://github.com/juju/errors">Juju&rsquo;s Errors</a></li>
</ul>
]]></content:encoded>
    </item>
    
    <item>
      <title>Golang &amp; MongoDB with &#34;Polymorphism&#34; and BSON Unmarshal</title>
      <link>https://haseebmajid.dev/posts/2020-12-20-golang-mongodb-with-polymorphism-and-bson-unmarshal/</link>
      <pubDate>Sun, 20 Dec 2020 00:00:00 +0000</pubDate>
      
      <guid>https://haseebmajid.dev/posts/2020-12-20-golang-mongodb-with-polymorphism-and-bson-unmarshal/</guid>
      <description>&lt;p&gt;Recently I&amp;rsquo;ve been working on a new personal project called Banter Bus, a browser-based multiplayer game.
I&amp;rsquo;ve been working on a REST API to add new questions to the game. The API is built in Golang and uses
MongoDB as the database. Since Golang is a strongly typed language, we will need to specify the structure of
the data we expect from the database. This can get tricky if the data varies, such as one field changing.&lt;/p&gt;</description>
      <content:encoded><![CDATA[<p>Recently I&rsquo;ve been working on a new personal project called Banter Bus, a browser-based multiplayer game.
I&rsquo;ve been working on a REST API to add new questions to the game. The API is built in Golang and uses
MongoDB as the database. Since Golang is a strongly typed language, we will need to specify the structure of
the data we expect from the database. This can get tricky if the data varies, such as one field changing.</p>
<p>One issue I encountered was each game type has to have its questions. These questions will be asked to the
users playing the game and are stored differently in the database. This is because each game type has different
rules and therefore needs a different structure. This means when we unmarshal the data in Golang,
we need to specify the structure of these questions. In this article, I will explain how you can create
your own unmarshal function. This will allow you to customise the struct that will hold this data (in Golang)
returned from MongoDB.</p>
<h2 id="collection">Collection</h2>
<p>Imagine the data stored in MongoDB looks something like so:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-json" data-lang="json"><span class="line"><span class="cl"><span class="p">[</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;game_name&#34;</span><span class="p">:</span> <span class="s2">&#34;fibbing_it&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;questions&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;opinion&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;horse_group&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;questions&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;What do you think about horses?&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">            <span class="s2">&#34;What do you think about camels?&#34;</span>
</span></span><span class="line"><span class="cl">          <span class="p">],</span>
</span></span><span class="line"><span class="cl">          <span class="nt">&#34;answers&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;lame&#34;</span><span class="p">,</span> <span class="s2">&#34;tasty&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">        <span class="p">}</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;free_form&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">        <span class="nt">&#34;bike_group&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;Favourite bike colour?&#34;</span><span class="p">,</span> <span class="s2">&#34;A funny question?&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">      <span class="p">},</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;likely&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;to eat ice-cream from the tub&#34;</span><span class="p">,</span> <span class="s2">&#34;to get arrested&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;game_name&#34;</span><span class="p">:</span> <span class="s2">&#34;quibly&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;questions&#34;</span><span class="p">:</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;pair&#34;</span><span class="p">:</span> <span class="p">[</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;What do you think about horses?&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">        <span class="s2">&#34;What do you think about camels?&#34;</span>
</span></span><span class="line"><span class="cl">      <span class="p">],</span>
</span></span><span class="line"><span class="cl">      <span class="nt">&#34;answers&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;Favourite bike colour?&#34;</span><span class="p">,</span> <span class="s2">&#34;A funny question?&#34;</span><span class="p">]</span>
</span></span><span class="line"><span class="cl">    <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">},</span>
</span></span><span class="line"><span class="cl">  <span class="p">{</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;game_name&#34;</span><span class="p">:</span> <span class="s2">&#34;drawlosseum&#34;</span><span class="p">,</span>
</span></span><span class="line"><span class="cl">    <span class="nt">&#34;questions&#34;</span><span class="p">:</span> <span class="p">{</span> <span class="nt">&#34;drawings&#34;</span><span class="p">:</span> <span class="p">[</span><span class="s2">&#34;horses&#34;</span><span class="p">,</span> <span class="s2">&#34;camels&#34;</span><span class="p">]</span> <span class="p">}</span>
</span></span><span class="line"><span class="cl">  <span class="p">}</span>
</span></span><span class="line"><span class="cl"><span class="p">]</span>
</span></span></code></pre></div><p>Here you can see each game type has a different structure, due to the different rules each game type
will have.</p>
<h2 id="unmarshal">Unmarshal</h2>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">BSON</summary>
  
  Binary JSON the format used by MongoDB readme more about it <a href="https://www.mongodb.com/json-and-bson">here</a>
</details>

<p>To do this we need to create a custom BSON unmarshal function. This will work very similarly to JSON unmarshaling.
When we try to get data from MongoDB, doing something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="nx">collection</span> <span class="o">:=</span> <span class="nx">_database</span><span class="p">.</span><span class="nf">Collection</span><span class="p">(</span><span class="s">&#34;games&#34;</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">err</span> <span class="o">:=</span> <span class="nx">collection</span><span class="p">.</span><span class="nf">FindOne</span><span class="p">(</span><span class="nx">_ctx</span><span class="p">,</span> <span class="nx">bson</span><span class="p">.</span><span class="nx">M</span><span class="p">{</span><span class="s">&#34;game_name&#34;</span><span class="p">:</span> <span class="s">&#34;quibly&#34;</span><span class="p">}).</span><span class="nf">Decode</span><span class="p">(</span><span class="kd">interface</span><span class="p">{}{})</span>
</span></span></code></pre></div><p>When decoding the object into a struct, MongoDB checks that the (struct) type implements the <code>Umarshaler</code> interface.
It implements this interface if it implements the <code>UnmarshalBSONValue(t bsontype.Type, data []byte) error</code> function.
If the struct type does implement this function, it will use this function instead of the default <code>UnmarshalBSONValue()</code>
function.</p>
<h3 id="example">Example</h3>
<p>Let&rsquo;s take a look at an example, define the following struct.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">QuestionSet</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">GameName</span>  <span class="kt">string</span>      <span class="s">`bson:&#34;game_name&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Questions</span> <span class="kd">interface</span><span class="p">{}</span> <span class="s">`bson:&#34;questions&#34;`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>Where the <code>Questions</code> field is the one that can vary between the different game types. Now let&rsquo;s define
the structure of the different game type. As you can see each of the game types will have different
rounds and ask different types of questions.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">DrawlosseumQuestionsPool</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Drawings</span> <span class="p">[]</span><span class="kt">string</span> <span class="s">`bson:&#34;drawings,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">QuiblyQuestionsPool</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Pair</span>    <span class="p">[]</span><span class="kt">string</span> <span class="s">`bson:&#34;pair,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Answers</span> <span class="p">[]</span><span class="kt">string</span> <span class="s">`bson:&#34;answers,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Group</span>   <span class="p">[]</span><span class="kt">string</span> <span class="s">`bson:&#34;group,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"><span class="kd">type</span> <span class="nx">FibbingItQuestionsPool</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Opinion</span>  <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">]</span><span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">][]</span><span class="kt">string</span> <span class="s">`bson:&#34;opinion,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">FreeForm</span> <span class="kd">map</span><span class="p">[</span><span class="kt">string</span><span class="p">][]</span><span class="kt">string</span>            <span class="s">`bson:&#34;free_form,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl">	<span class="nx">Likely</span>   <span class="p">[]</span><span class="kt">string</span>                       <span class="s">`bson:&#34;likely,omitempty&#34;`</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>To get the <code>QuestionSet</code> struct to implement the <code>Unmarshaler</code> interface we need to do something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl"><span class="kd">func</span> <span class="p">(</span><span class="nx">questionSet</span> <span class="o">*</span><span class="nx">QuestionSet</span><span class="p">)</span> <span class="nf">UnmarshalBSONValue</span><span class="p">(</span><span class="nx">t</span> <span class="nx">bsontype</span><span class="p">.</span><span class="nx">Type</span><span class="p">,</span> <span class="nx">data</span> <span class="p">[]</span><span class="kt">byte</span><span class="p">)</span> <span class="kt">error</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">rawData</span> <span class="nx">bson</span><span class="p">.</span><span class="nx">Raw</span>
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="o">:=</span> <span class="nx">bson</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">rawData</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="p">=</span> <span class="nx">rawData</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionSet</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">questions</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Questions</span> <span class="nx">bson</span><span class="p">.</span><span class="nx">Raw</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="p">=</span> <span class="nx">rawData</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questions</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">switch</span> <span class="nx">questionPool</span><span class="p">.</span><span class="nx">GameName</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">case</span> <span class="s">&#34;drawlosseum&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">DrawlosseumQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">		<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span><span class="line"><span class="cl">	<span class="k">case</span> <span class="s">&#34;quibly&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">QuiblyQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">		<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span><span class="line"><span class="cl">	<span class="k">case</span> <span class="s">&#34;fibbing_it&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">FibbingItQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">		<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span><span class="line"><span class="cl">	<span class="k">default</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;Unknown game name %s&#34;</span><span class="p">,</span> <span class="nx">questionPool</span><span class="p">.</span><span class="nx">GameName</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>This function looks very complicated so let&rsquo;s break it down and explain what&rsquo;s going on.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">rawData</span> <span class="nx">bson</span><span class="p">.</span><span class="nx">Raw</span>
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="o">:=</span> <span class="nx">bson</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="nx">data</span><span class="p">,</span> <span class="o">&amp;</span><span class="nx">rawData</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span></code></pre></div><p>First, we need to unmarshal the data into BSON raw data. We need the BSON raw data because it allows
us to partially unmarshal values. You can read more about it <a href="https://godoc.org/gopkg.in/mgo.v2/bson#Raw">here</a>.</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="nx">err</span> <span class="p">=</span> <span class="nx">rawData</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionSet</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span></code></pre></div><p>Next, we need to unmarshal the data into the <code>QuestionSet</code> struct, this is mainly to fill all the other fields (<code>GameName</code>)
besides <code>Questions</code>.</p>
<details
  class="notice info"
  open="true"
>
    <summary class="notice-title">Names</summary>
  
  The struct tags we&rsquo;ve defined <code>bson:&quot;x&quot;</code> should match the name of that field in the database, else the unmarshaling will not
work correctly i.e. the struct fields will be <code>nil</code>.
</details>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="kd">var</span> <span class="nx">questions</span> <span class="kd">struct</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="nx">Questions</span> <span class="nx">bson</span><span class="p">.</span><span class="nx">Raw</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="p">=</span> <span class="nx">rawData</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questions</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="k">if</span> <span class="nx">err</span> <span class="o">!=</span> <span class="kc">nil</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">err</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span></code></pre></div><p>Now onto the part that deals with the <code>Questions</code> field. Here we get the raw BSON data only related to the <code>Questions</code> field. So it won&rsquo;t have anything
related to <code>GameName</code>. We create a &ldquo;temporary&rdquo; struct to hold this BSON data, with the same field name.</p>
<details
  class="notice warning"
  open="true"
>
    <summary class="notice-title">BSON Struct Tags</summary>
  
  If your field has an <code>_</code> or something else a bit different, you should use the <code>bson</code> struct tags
to specify the name of the field in the database.
</details>

<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="k">switch</span> <span class="nx">questionPool</span><span class="p">.</span><span class="nx">GameName</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl">	<span class="k">case</span> <span class="s">&#34;drawlosseum&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">DrawlosseumQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">		<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span><span class="line"><span class="cl">	<span class="k">case</span> <span class="s">&#34;quibly&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">QuiblyQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">		<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span><span class="line"><span class="cl">	<span class="k">case</span> <span class="s">&#34;fibbing_it&#34;</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">FibbingItQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">		<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">		<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span><span class="line"><span class="cl">	<span class="k">default</span><span class="p">:</span>
</span></span><span class="line"><span class="cl">		<span class="k">return</span> <span class="nx">errors</span><span class="p">.</span><span class="nf">Errorf</span><span class="p">(</span><span class="s">&#34;Unknown game name %s&#34;</span><span class="p">,</span> <span class="nx">questionPool</span><span class="p">.</span><span class="nx">GameName</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="p">}</span>
</span></span></code></pre></div><p>Finally, let&rsquo;s take a look at the code that unmarshal our questions into the correct structs.
We will use a switch type statement. In this example, the <code>GameName</code> will determine how the questions
are stored. Each case looks something like:</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-go" data-lang="go"><span class="line"><span class="cl">	<span class="nx">questionStructure</span> <span class="o">:=</span> <span class="nx">DrawlosseumQuestionsPool</span><span class="p">{}</span>
</span></span><span class="line"><span class="cl">	<span class="nx">err</span> <span class="p">=</span> <span class="nx">questions</span><span class="p">.</span><span class="nx">Questions</span><span class="p">.</span><span class="nf">Unmarshal</span><span class="p">(</span><span class="o">&amp;</span><span class="nx">questionStructure</span><span class="p">)</span>
</span></span><span class="line"><span class="cl">	<span class="nx">questionPool</span><span class="p">.</span><span class="nx">Questions</span> <span class="p">=</span> <span class="nx">questionStructure</span>
</span></span></code></pre></div><p>We define the correct struct to use. Then we unmarshal the raw BSON data into this struct. We then assign this struct
to the <code>questionPool</code> variable. This is what will be &ldquo;returned&rdquo; when we use <code>FindOne</code> function shown above.</p>
<p>That&rsquo;s it! We&rsquo;ve now created our custom unmarshal function for dealing with polymorphic data stored in MongoDB in
Golang.</p>
<h2 id="appendix">Appendix</h2>
<ul>
<li><a href="https://github.com/mongodb/mongo-go-driver/">Cover Photo</a></li>
<li><a href="https://gitlab.com/banter-bus/banter-bus-server/-/blob/39c05ef7e3097697e25343b47f4846d11f9e7ae5/src/core/models/user_models.go#L86-125">Example Project</a></li>
</ul>
]]></content:encoded>
    </item>
    
  </channel>
</rss>
