<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>DEV Community: y-yagi</title>
    <description>The latest articles on DEV Community by y-yagi (@yyagi).</description>
    <link>https://dev.to/yyagi</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F43081%2F6d1b1ff1-a188-400b-83e0-85256fcf67fd.jpeg</url>
      <title>DEV Community: y-yagi</title>
      <link>https://dev.to/yyagi</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/yyagi"/>
    <language>en</language>
    <item>
      <title>CLI for Windows with Go</title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Sun, 13 Dec 2020 04:49:02 +0000</pubDate>
      <link>https://dev.to/yyagi/cli-for-windows-with-go-4k2g</link>
      <guid>https://dev.to/yyagi/cli-for-windows-with-go-4k2g</guid>
      <description>&lt;p&gt;Recently, I created a CLI for windows. I learned about some TIPS. Let's describe that in this article. Sample code exists in &lt;a href="https://github.com/y-yagi/cli-for-windows" rel="noopener noreferrer"&gt;https://github.com/y-yagi/cli-for-windows&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  "GUI binary" or "console binary"
&lt;/h2&gt;

&lt;p&gt;By default, Go build a binary as "console binary". This means a window console is kept showing when a binary is executed. It is good for applications that will finish immediately. But that's not good for some kind of applications(e.g. GUI application, HTTP server).&lt;/p&gt;

&lt;p&gt;In the case of such applications, we can build binary as "GUI binary". In "GUI binary", a window console doesn't show when a binary is executed.&lt;/p&gt;

&lt;p&gt;In order to build with "GUI binary", you need to specify "-H windowsgui" to ldflags.&lt;br&gt;
On Windows, -H windowsgui writes a "GUI binary" instead of a "console binary."&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go build &lt;span class="nt"&gt;-ldflags&lt;/span&gt; &lt;span class="s2"&gt;"-H windowsgui"&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;See also: &lt;a href="https://github.com/golang/go/blob/3b2a578166bdedd94110698c971ba8990771eb89/src/cmd/link/doc.go#L28" rel="noopener noreferrer"&gt;https://github.com/golang/go/blob/3b2a578166bdedd94110698c971ba8990771eb89/src/cmd/link/doc.go#L28&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Embed icon to a binary file
&lt;/h2&gt;

&lt;p&gt;Maybe you want to include an icon in your CLI. Go build binary as a &lt;a href="https://en.wikipedia.org/wiki/Portable_Executable" rel="noopener noreferrer"&gt;&lt;code&gt;Portable Executable&lt;/code&gt;&lt;/a&gt; format. Portable Executable format has a section for resources(rsrc section). We need to add an icon to that section.&lt;/p&gt;

&lt;p&gt;When embed data to Go binary, need to prepare &lt;code&gt;syso&lt;/code&gt; file. There is a tool called &lt;a href="https://github.com/akavel/rsrc" rel="noopener noreferrer"&gt;rsrc&lt;/a&gt; that will generate &lt;code&gt;syso&lt;/code&gt; file for embedding in the rsrc section, so let's use that.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go get github.com/akavel/rsrc
&lt;span class="nv"&gt;$ &lt;/span&gt;rsrc &lt;span class="nt"&gt;-ico&lt;/span&gt; your-icon.ico &lt;span class="nt"&gt;-arch&lt;/span&gt;&lt;span class="o"&gt;=&lt;/span&gt;amd64
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to prepare &lt;code&gt;syso&lt;/code&gt; files per architecture. &lt;code&gt;syso&lt;/code&gt; file will link automatically when run &lt;code&gt;go build&lt;/code&gt;. So we don't need to specify options or files to &lt;code&gt;go build&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;See also: &lt;a href="https://github.com/golang/go/wiki/GcToolchainTricks#use-syso-file-to-embed-arbitrary-self-contained-c-code" rel="noopener noreferrer"&gt;GcToolchainTricks · golang/go Wiki&lt;/a&gt;&lt;/p&gt;

&lt;h2&gt;
  
  
  Notification Area
&lt;/h2&gt;

&lt;p&gt;If you choose "GUI binary" applications, maybe we need to consider how the exit of applications.&lt;br&gt;
In the case of "console binary", if want to exit, simplify close the console. But in the case of "GUI binary", we can't do that.&lt;br&gt;
Of course, we can exit applications via the Task Manager. But maybe it difficult for people who unfamiliar with Windows.&lt;/p&gt;

&lt;p&gt;So let's consider to use "Notification Area"(or called "System Tray").&lt;/p&gt;

&lt;p&gt;The notification area is located at the right end of the taskbar, it can be operated to applications by GUI.&lt;/p&gt;

&lt;p&gt;Of course, already exists that library for using Notification Area.&lt;br&gt;
&lt;a href="https://github.com/getlantern/systray" rel="noopener noreferrer"&gt;getlantern/systray&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;Here's an example code with &lt;code&gt;systray&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;systray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;onReady&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// (1)&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;onReady&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;systray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetIcon&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;icon&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// (2)&lt;/span&gt;
    &lt;span class="n"&gt;systray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTitle&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My CLI"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;systray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;SetTooltip&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"My CLI"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;mQuit&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;systray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;AddMenuItem&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"Quit"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Quit"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="c"&gt;// (3)&lt;/span&gt;
    &lt;span class="o"&gt;&amp;lt;-&lt;/span&gt;&lt;span class="n"&gt;mQuit&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ClickedCh&lt;/span&gt;
    &lt;span class="n"&gt;systray&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Quit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;onExit&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c"&gt;// clean up&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(1) &lt;code&gt;systray.Run&lt;/code&gt; initializes GUI and starts the event loop. Also, you can pass two functions that run when applications starting and exiting.&lt;br&gt;
(2) &lt;code&gt;systray.SetIcon&lt;/code&gt; accept to array bytes of icon data. This means you need to prepare array bytes of an icon. &lt;a href="https://github.com/cratonica/2goarray" rel="noopener noreferrer"&gt;2goarray&lt;/a&gt; can use in this case. &lt;code&gt;2goarray&lt;/code&gt; can encode files into array bytes.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;go get github.com/cratonica/2goarray
&lt;span class="nv"&gt;$ &lt;/span&gt;2goarray icon main &amp;lt; icon.png &lt;span class="o"&gt;&amp;gt;&lt;/span&gt; icon.go
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(3) &lt;code&gt;systray.AddMenuItem&lt;/code&gt; add a menu item to an application. In this example, add a menu item that quit an application.&lt;/p&gt;

&lt;p&gt;This example shows as follows on Windows.&lt;/p&gt;

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

&lt;h2&gt;
  
  
  CI
&lt;/h2&gt;

&lt;p&gt;Of course, we need to consider the CI. Before, we have little choice for CI. But now we have some choices. For example, &lt;a href="https://www.appveyor.com/" rel="noopener noreferrer"&gt;AppVeyor&lt;/a&gt;, &lt;a href="https://circleci.com/build-environments/windows/" rel="noopener noreferrer"&gt;CircleCI&lt;/a&gt;, and &lt;a href="https://github.co.jp/features/actions" rel="noopener noreferrer"&gt;GitHub Actions&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;In my personal opinion, if you are using GitHub, I recommend GitHub Actions. Because it can use easily and don't' need to create an extra account.&lt;/p&gt;

&lt;p&gt;An example of GitHub Actions is the following. It needs to add a file to &lt;code&gt;.github/workflows/&lt;/code&gt; directory for use(e.g. &lt;code&gt;.github/workflows/ci.yml&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;CI&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;[&lt;/span&gt;&lt;span class="nv"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;]&lt;/span&gt;
&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

  &lt;span class="na"&gt;build&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Build&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;windows-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Go&lt;/span&gt; &lt;span class="c1"&gt;# (1)&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v2&lt;/span&gt;
      &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.15&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check out code&lt;/span&gt; &lt;span class="c1"&gt;# (2)&lt;/span&gt;
      &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

    &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run test (3)&lt;/span&gt;
      &lt;span class="na"&gt;run&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="pi"&gt;|&lt;/span&gt;
        &lt;span class="s"&gt;go test ./...&lt;/span&gt;
      &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
        &lt;span class="na"&gt;GO111MODULE&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;on&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(1) Set up Go environment by &lt;a href="https://github.com/actions/setup-go" rel="noopener noreferrer"&gt;setup-go&lt;/a&gt; action.&lt;br&gt;
(2) Checks-out my repository by &lt;a href="https://github.com/actions/checkout" rel="noopener noreferrer"&gt;checkout&lt;/a&gt; action.&lt;br&gt;
(3) Run tests.&lt;/p&gt;

&lt;p&gt;That's it!&lt;/p&gt;

&lt;p&gt;If you want to run &lt;code&gt;golangci-lint&lt;/code&gt; in CI, you can use &lt;a href="https://github.com/golangci/golangci-lint-action" rel="noopener noreferrer"&gt;golangci-lint-action&lt;/a&gt; same as other actions.&lt;/p&gt;
&lt;h2&gt;
  
  
  Release
&lt;/h2&gt;

&lt;p&gt;Finally, let's consider the management of release binaries. If you are using GitHub, I think &lt;a href="https://docs.github.com/en/free-pro-team@latest/github/administering-a-repository/about-releases" rel="noopener noreferrer"&gt;GitHub Releases&lt;/a&gt; is good for that. It can manage source and binaries in the same place.&lt;/p&gt;

&lt;p&gt;GitHub Releases are based on Git tags. So I wanted to upload binaries to GitHub Releases when push gi tags. We can use GitHub Actions also this case. Here is an example of a setting.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Release&lt;/span&gt;
&lt;span class="na"&gt;on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;push&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;tags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s1"&gt;'&lt;/span&gt;&lt;span class="s"&gt;v*'&lt;/span&gt; &lt;span class="c1"&gt;# (1)&lt;/span&gt;

&lt;span class="na"&gt;jobs&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;windows&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;runs-on&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;windows-latest&lt;/span&gt;
    &lt;span class="na"&gt;steps&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Set up Go&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/setup-go@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;go-version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="m"&gt;1.15&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Check out code into the Go module directory&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;actions/checkout@v2&lt;/span&gt;

      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;Run release&lt;/span&gt; &lt;span class="c1"&gt;# (2)&lt;/span&gt;
        &lt;span class="na"&gt;uses&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;goreleaser/goreleaser-action@v2&lt;/span&gt;
        &lt;span class="na"&gt;with&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;version&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;latest&lt;/span&gt;
          &lt;span class="na"&gt;args&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;release --rm-dist&lt;/span&gt;
        &lt;span class="na"&gt;env&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
          &lt;span class="na"&gt;GITHUB_TOKEN&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;${{ secrets.GITHUB_TOKEN }}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;(1) Restrict that only run when git tag started with &lt;code&gt;v&lt;/code&gt;(e.g. &lt;code&gt;v1.0.0&lt;/code&gt;).&lt;br&gt;
(2) Use &lt;a href="https://goreleaser.com/" rel="noopener noreferrer"&gt;GoReleaser&lt;/a&gt; action for upload binaries to GitHub Releases.&lt;/p&gt;

&lt;p&gt;&lt;code&gt;GoReleaser&lt;/code&gt; settings as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight yaml"&gt;&lt;code&gt;&lt;span class="na"&gt;builds&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="na"&gt;binary&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s2"&gt;"&lt;/span&gt;&lt;span class="s"&gt;MY&lt;/span&gt;&lt;span class="nv"&gt; &lt;/span&gt;&lt;span class="s"&gt;CLI"&lt;/span&gt;
    &lt;span class="na"&gt;goos&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;windows&lt;/span&gt;
    &lt;span class="na"&gt;ldflags&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;-H windowsgui&lt;/span&gt;
    &lt;span class="na"&gt;goarch&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="s"&gt;amd64&lt;/span&gt;
      &lt;span class="pi"&gt;-&lt;/span&gt; &lt;span class="m"&gt;386&lt;/span&gt;
&lt;span class="na"&gt;archives&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="pi"&gt;-&lt;/span&gt;
    &lt;span class="na"&gt;format&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;zip&lt;/span&gt;
&lt;span class="na"&gt;release&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
  &lt;span class="na"&gt;github&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt;
    &lt;span class="na"&gt;owner&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;y-yagi&lt;/span&gt;
    &lt;span class="na"&gt;name&lt;/span&gt;&lt;span class="pi"&gt;:&lt;/span&gt; &lt;span class="s"&gt;cli-for-windows&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You need to specify &lt;code&gt;github&lt;/code&gt; section under the &lt;code&gt;release&lt;/code&gt; section` for upload binaries to GitHub Releases.&lt;/p&gt;

</description>
      <category>go</category>
      <category>windows</category>
    </item>
    <item>
      <title>Automatically change Go version with `gvm` and `zsh`</title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Thu, 26 Mar 2020 02:55:43 +0000</pubDate>
      <link>https://dev.to/yyagi/automatically-change-go-version-with-gvm-and-zsh-58c3</link>
      <guid>https://dev.to/yyagi/automatically-change-go-version-with-gvm-and-zsh-58c3</guid>
      <description>&lt;p&gt;&lt;code&gt;gvm&lt;/code&gt; does not change Go version automatically. This is a little inconvenience when developing multiple projects that use different Go versions. Let's change Go version when moved to the directory of Go project like &lt;code&gt;rbenv&lt;/code&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Get Go version
&lt;/h2&gt;

&lt;p&gt;Normally, we don't have a file that described Go version(like &lt;code&gt;.ruby-version&lt;/code&gt;, &lt;code&gt;.node-version&lt;/code&gt;). &lt;br&gt;
But since Go 1.12, &lt;code&gt;go.mod&lt;/code&gt; includes Go version &lt;a href="https://github.com/golang/go/issues/28221"&gt;1&lt;/a&gt;. This probably the same with the projects' Go version. Let's reuse this.  &lt;/p&gt;

&lt;p&gt;This can do as following with &lt;code&gt;zsh&lt;/code&gt;.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;_change_go_version&lt;span class="o"&gt;()&lt;/span&gt; &lt;span class="o"&gt;{&lt;/span&gt;
  &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="o"&gt;[&lt;/span&gt; &lt;span class="nt"&gt;-f&lt;/span&gt; &lt;span class="s2"&gt;"go.mod"&lt;/span&gt; &lt;span class="o"&gt;]&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt; &lt;span class="k"&gt;then
    &lt;/span&gt;&lt;span class="nb"&gt;local &lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="o"&gt;=(&lt;/span&gt;&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="nb"&gt;grep&lt;/span&gt; &lt;span class="nt"&gt;-Po&lt;/span&gt; &lt;span class="s2"&gt;"^go &lt;/span&gt;&lt;span class="se"&gt;\K&lt;/span&gt;&lt;span class="s2"&gt;([0-9&lt;/span&gt;&lt;span class="se"&gt;\.&lt;/span&gt;&lt;span class="s2"&gt;]*)$"&lt;/span&gt; go.mod&lt;span class="sb"&gt;`&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt;
    gvm use &lt;span class="k"&gt;${&lt;/span&gt;&lt;span class="nv"&gt;version&lt;/span&gt;&lt;span class="k"&gt;}&lt;/span&gt;
  &lt;span class="k"&gt;fi&lt;/span&gt;
&lt;span class="o"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;h2&gt;
  
  
  Change Go version when directory changed
&lt;/h2&gt;

&lt;p&gt;zsh provides some hook functions. One of them, &lt;code&gt;chpwd&lt;/code&gt; executed whenever the current working directory is changed &lt;a href="http://zsh.sourceforge.net/Doc/Release/Functions.html"&gt;2&lt;/a&gt;. This function can use inside &lt;code&gt;zshrc&lt;/code&gt;. Let's call &lt;code&gt;_change_go_version&lt;/code&gt; inside this function.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight plaintext"&gt;&lt;code&gt;# .zshrc
chpwd()
{
  _change_go_version
}
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;As a result, autosomally call &lt;code&gt;gvm use&lt;/code&gt; when moved directory that has the &lt;code&gt;go.mod&lt;/code&gt; file. If you use another version manager, please change &lt;code&gt;gvm use&lt;/code&gt; inside &lt;code&gt;_change_go_version&lt;/code&gt;. &lt;/p&gt;

&lt;p&gt;Have a nice day!&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Intro to `cacher` that simple cache library</title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Fri, 04 Oct 2019 00:18:30 +0000</pubDate>
      <link>https://dev.to/yyagi/intro-to-cacher-that-simple-cache-library-2f72</link>
      <guid>https://dev.to/yyagi/intro-to-cacher-that-simple-cache-library-2f72</guid>
      <description>&lt;p&gt;I created the cache library for the Go language. It's named &lt;code&gt;cacher&lt;/code&gt;.&lt;br&gt;
GitHub: &lt;a href="https://github.com/y-yagi/cacher"&gt;https://github.com/y-yagi/cacher&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;code&gt;cacher&lt;/code&gt; supports to use a file system to store cache data.&lt;/p&gt;
&lt;h2&gt;
  
  
  Why this need?
&lt;/h2&gt;

&lt;p&gt;I create CLI tools often and sometimes want to use cache in that. For example, when the same HTTP API is called many times and the result of API rarely changes.&lt;br&gt;
Normally, using Redis or memcached(or something similar) for the cache. But in the case of CLI, it may not be using those middlewares. So I wanted a cache library that supports to file system.&lt;/p&gt;
&lt;h2&gt;
  
  
  How to use
&lt;/h2&gt;

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

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

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

    &lt;span class="s"&gt;"github.com/y-yagi/cacher"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// Specify a directory that stores cache data.&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;cacher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;WithFileStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"/tmp/"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// Arguments are cache key, data and expiry time. If uses `cacher.Forever`, cache never expires.&lt;/span&gt;
    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cache-key"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;cacher&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Forever&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cache-key"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;

    &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Write&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cache-key2"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Sleep&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt; &lt;span class="n"&gt;time&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Second&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="c"&gt;// If the cache expired. `Read` returns nil.&lt;/span&gt;
    &lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;c&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Read&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"cache-key2"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Print&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;value&lt;/span&gt;&lt;span class="p"&gt;))&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For more detail, please see the &lt;a href="https://godoc.org/github.com/y-yagi/cacher"&gt;API doc&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  How to store data to file?
&lt;/h2&gt;

&lt;p&gt;Go supports multiple formats to store data. This time I use &lt;code&gt;gob&lt;/code&gt; package. The &lt;code&gt;gob&lt;/code&gt; package can handle Go data structure as is. A simple example is followed.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"bytes"&lt;/span&gt;
    &lt;span class="s"&gt;"encoding/gob"&lt;/span&gt;
    &lt;span class="s"&gt;"fmt"&lt;/span&gt;
    &lt;span class="s"&gt;"log"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;type&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="k"&gt;struct&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;Value&lt;/span&gt;      &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;
    &lt;span class="n"&gt;Expiration&lt;/span&gt; &lt;span class="kt"&gt;int64&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;{&lt;/span&gt;&lt;span class="n"&gt;Value&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"value"&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt; &lt;span class="n"&gt;Expiration&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="n"&gt;encodedEntry&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%#v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;encodedEntry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;decodedEntry&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;encodedEntry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;fmt&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Printf&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"%#v&lt;/span&gt;&lt;span class="se"&gt;\n&lt;/span&gt;&lt;span class="s"&gt;"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;decodedEntry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewEncoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Encode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"encode error:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Bytes&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;byte&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;entry&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;e&lt;/span&gt; &lt;span class="n"&gt;entry&lt;/span&gt;
    &lt;span class="n"&gt;buf&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;bytes&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewBuffer&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;data&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;gob&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewDecoder&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;buf&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Decode&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt; &lt;span class="o"&gt;!=&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="n"&gt;log&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Fatal&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"decode error:"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;err&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;e&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For more detail, please see the &lt;a href="https://blog.golang.org/gobs-of-data"&gt;blog entry&lt;/a&gt; and &lt;a href="https://golang.org/pkg/encoding/gob/"&gt;API doc&lt;/a&gt;.&lt;/p&gt;

&lt;h2&gt;
  
  
  Wrapping up
&lt;/h2&gt;

&lt;p&gt;I introduced my cache library that assumed to using CLI. But may more appropriate approaches/libraries exist I think. If you know something, please tell me. Thanks!&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Show parameter name in usage message of flag</title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Sun, 18 Nov 2018 07:37:34 +0000</pubDate>
      <link>https://dev.to/yyagi/show-parameter-name-in-usage-message-of-flag---2079</link>
      <guid>https://dev.to/yyagi/show-parameter-name-in-usage-message-of-flag---2079</guid>
      <description>&lt;p&gt;Flag package provides features about command-line flag parsing. It includes a usage message of course. For example, it shows them as following.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"flag"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;importFile&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFlagSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mycmd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitOnError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;importFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"import"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"import file."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoolVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"edit config."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"number of executions."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./mycmd --help
Usage of mycmd:
  -c    edit config.
  -import string
        import file.
  -n int
        number of executions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;This build automatically. The parameter name uses the flag's type. But sometimes want to customize parameter name. &lt;br&gt;
For example, in the example above, I would like to use &lt;code&gt;file&lt;/code&gt; as an argument to &lt;code&gt;-import&lt;/code&gt; and &lt;code&gt;number&lt;/code&gt; as an argument to &lt;code&gt;-n&lt;/code&gt;(Because that is surely more natural ;)).  &lt;/p&gt;

&lt;p&gt;This can specify from &lt;code&gt;usage&lt;/code&gt; argument &lt;code&gt;xxVar&lt;/code&gt; methods. If includes a back-quoted name in &lt;code&gt;usage&lt;/code&gt;, it uses for the parameter name.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"flag"&lt;/span&gt;
    &lt;span class="s"&gt;"os"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;importFile&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;config&lt;/span&gt; &lt;span class="kt"&gt;bool&lt;/span&gt;
    &lt;span class="k"&gt;var&lt;/span&gt; &lt;span class="n"&gt;number&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt;

    &lt;span class="n"&gt;flags&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewFlagSet&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="s"&gt;"mycmd"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;flag&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;ExitOnError&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;StringVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;importFile&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"import"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Import `file`."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;BoolVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;config&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"c"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;false&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"Edit config."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;IntVar&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="o"&gt;&amp;amp;&lt;/span&gt;&lt;span class="n"&gt;number&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"n"&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="s"&gt;"`Number` of executions."&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;

    &lt;span class="n"&gt;flags&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Parse&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;os&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;Args&lt;/span&gt;&lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="m"&gt;1&lt;/span&gt;&lt;span class="o"&gt;:&lt;/span&gt;&lt;span class="p"&gt;])&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;





&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;$ ./mycmd --help 
Usage of mycmd:
  -c    edit config.
  -import file
        import file.
  -n number
        number of executions.
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;I didn't know long about this. This describes in the doc of &lt;a href="https://golang.org/pkg/flag/#PrintDefaults" rel="noopener noreferrer"&gt;&lt;code&gt;PrintDefaults&lt;/code&gt; func&lt;/a&gt;.  &lt;/p&gt;

&lt;p&gt;I hope this helps someone.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Avoiding the `master` branch is used in `go get`</title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Wed, 31 Oct 2018 04:44:12 +0000</pubDate>
      <link>https://dev.to/yyagi/avoiding-the-master-branch-is-used-in-go-get--4p3k</link>
      <guid>https://dev.to/yyagi/avoiding-the-master-branch-is-used-in-go-get--4p3k</guid>
      <description>&lt;p&gt;&lt;code&gt;go get&lt;/code&gt; retrieves the default branch of the package by default. This is often using the &lt;code&gt;master&lt;/code&gt; branch. But the &lt;code&gt;master&lt;/code&gt; branch is including work in progress code sometimes, so want to avoid to use it. &lt;br&gt;
To solve this problem, there is an approach of dividing the default branch and the development branch. But this is just a little complex.  &lt;/p&gt;

&lt;p&gt;Other approaches to solving this problem, use a branch or tag named &lt;code&gt;go1&lt;/code&gt;. &lt;br&gt;
&lt;code&gt;go get&lt;/code&gt; has a rule for looks for a branch of tag that matches the locally installed version of Go. It describes in the doc.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;When checking out or updating a package, get looks for a branch or tag that matches the locally installed version of Go. The most important rule is that if the local installation is running version "go1", get searches for a branch or tag named "go1". If no such version exists it retrieves the default branch of the package.  
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://golang.org/cmd/go/#hdr-Download_and_install_packages_and_dependencies" rel="noopener noreferrer"&gt;https://golang.org/cmd/go/#hdr-Download_and_install_packages_and_dependencies&lt;/a&gt;  &lt;/p&gt;

&lt;p&gt;This is also can confirm in &lt;code&gt;get.go&lt;/code&gt;. Below is the code of the corresponding part.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// selectTag returns the closest matching tag for a given version.&lt;/span&gt;
&lt;span class="c"&gt;// Closest means the latest one that is not after the current release.&lt;/span&gt;
&lt;span class="c"&gt;// Version "goX" (or "goX.Y" or "goX.Y.Z") matches tags of the same form.&lt;/span&gt;
&lt;span class="c"&gt;// Version "release.rN" matches tags of the form "go.rN" (N being a floating-point number).&lt;/span&gt;
&lt;span class="c"&gt;// Version "weekly.YYYY-MM-DD" matches tags like "go.weekly.YYYY-MM-DD".&lt;/span&gt;
&lt;span class="c"&gt;//&lt;/span&gt;
&lt;span class="c"&gt;// NOTE(rsc): Eventually we will need to decide on some logic here.&lt;/span&gt;
&lt;span class="c"&gt;// For now, there is only "go1". This matches the docs in go help get.&lt;/span&gt;
&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;selectTag&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;goVersion&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;[]&lt;/span&gt;&lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;match&lt;/span&gt; &lt;span class="kt"&gt;string&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;for&lt;/span&gt; &lt;span class="n"&gt;_&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;:=&lt;/span&gt; &lt;span class="k"&gt;range&lt;/span&gt; &lt;span class="n"&gt;tags&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
        &lt;span class="k"&gt;if&lt;/span&gt; &lt;span class="n"&gt;t&lt;/span&gt; &lt;span class="o"&gt;==&lt;/span&gt; &lt;span class="s"&gt;"go1"&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
            &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;"go1"&lt;/span&gt;
        &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="s"&gt;""&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;a href="https://github.com/golang/go/blob/fde4b9ed14e339b5064373c1d4a73e211ec32ac4/src/cmd/go/internal/get/get.go#L541-L556" rel="noopener noreferrer"&gt;https://github.com/golang/go/blob/fde4b9ed14e339b5064373c1d4a73e211ec32ac4/src/cmd/go/internal/get/get.go#L541-L556&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Unfortunately, we can use &lt;code&gt;go1&lt;/code&gt; tar or branch only now.  &lt;/p&gt;

&lt;p&gt;But can use &lt;code&gt;go1&lt;/code&gt; to control the version used. Let's try to use it.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Show comments in GoDoc </title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Sun, 21 Oct 2018 06:15:52 +0000</pubDate>
      <link>https://dev.to/yyagi/show-comments-in-godoc--1nog</link>
      <guid>https://dev.to/yyagi/show-comments-in-godoc--1nog</guid>
      <description>&lt;p&gt;GoDoc show comments in code when runs &lt;code&gt;godoc&lt;/code&gt; command with &lt;code&gt;notes&lt;/code&gt; option.  The &lt;code&gt;notes&lt;/code&gt; option can specify regular expression matching note markers to show(default is &lt;code&gt;BUG&lt;/code&gt;).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;godoc &lt;span class="nt"&gt;--help&lt;/span&gt;
usage: godoc package &lt;span class="o"&gt;[&lt;/span&gt;name ...] 
&lt;span class="o"&gt;(&lt;/span&gt;snip&lt;span class="o"&gt;)&lt;/span&gt;
  &lt;span class="nt"&gt;-notes&lt;/span&gt; string
        regular expression matching note markers to show &lt;span class="o"&gt;(&lt;/span&gt;default &lt;span class="s2"&gt;"BUG"&lt;/span&gt;&lt;span class="o"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





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

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

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;NewExter&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// TODO(who): implement&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;Exter&lt;/span&gt;&lt;span class="p"&gt;{}&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;exter&lt;/span&gt; &lt;span class="o"&gt;*&lt;/span&gt;&lt;span class="n"&gt;Exter&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="n"&gt;Run&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="kt"&gt;error&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="c"&gt;// BUG(who): Not return correct value&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;For example, there is a code the above, doc shows as follows.&lt;/p&gt;

&lt;p&gt;&lt;a href="https://res.cloudinary.com/practicaldev/image/fetch/s--TVhKPt5i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/djglmcrs1gb9lzznjll7.png" class="article-body-image-wrapper"&gt;&lt;img src="https://res.cloudinary.com/practicaldev/image/fetch/s--TVhKPt5i--/c_limit%2Cf_auto%2Cfl_progressive%2Cq_auto%2Cw_880/https://thepracticaldev.s3.amazonaws.com/i/djglmcrs1gb9lzznjll7.png" alt="doc"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;But if you remove &lt;code&gt;(who)&lt;/code&gt; from comment, comment not shows in GoDoc.   &lt;/p&gt;

&lt;p&gt;This is because of the limit of GoDoc. &lt;/p&gt;

&lt;p&gt;The notes need to write a comment as &lt;code&gt;MARKER(uid): note body&lt;/code&gt;. Also, &lt;code&gt;MAKER&lt;/code&gt; needs 2 or more uppercase [A-Z] letters and a &lt;code&gt;UID&lt;/code&gt; of at least one character.  &lt;/p&gt;

&lt;p&gt;This is describing at &lt;code&gt;Note&lt;/code&gt; type comment. &lt;br&gt;
&lt;a href="https://godoc.org/go/doc#Note"&gt;https://godoc.org/go/doc#Note&lt;/a&gt; &lt;/p&gt;

&lt;p&gt;Regex for &lt;code&gt;MARKER&lt;/code&gt; is here: &lt;a href="https://github.com/golang/go/blob/035f9e8102d3b46877b7462fcd365324272d1d0e/src/go/doc/reader.go#L435"&gt;https://github.com/golang/go/blob/035f9e8102d3b46877b7462fcd365324272d1d0e/src/go/doc/reader.go#L435&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is a little unusual for &lt;code&gt;(uid)&lt;/code&gt; to be mandatory (at least for me ;) ), so be careful.&lt;/p&gt;

</description>
      <category>go</category>
    </item>
    <item>
      <title>Check deprecated things in Go</title>
      <dc:creator>y-yagi</dc:creator>
      <pubDate>Thu, 11 Oct 2018 00:25:21 +0000</pubDate>
      <link>https://dev.to/yyagi/check-deprecated-things-in-go-5eh8</link>
      <guid>https://dev.to/yyagi/check-deprecated-things-in-go-5eh8</guid>
      <description>&lt;h2&gt;
  
  
  How deprecate functions?
&lt;/h2&gt;

&lt;p&gt;Go official suggest to using &lt;code&gt;Deprecated:&lt;/code&gt; comment in the doc that wants to deprecate functions, struct fields.&lt;br&gt;
&lt;a href="https://blog.golang.org/godoc-documenting-go-code"&gt;Godoc: documenting Go code&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;It is using in standard libraries. Ref: &lt;a href="https://golang.org/search?q=Deprecated:"&gt;standard library&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;For example, &lt;a href="https://golang.org/src/os/file.go?h=Deprecated%3A#L80"&gt;&lt;code&gt;SEEK_SET&lt;/code&gt; const&lt;/a&gt; of &lt;code&gt;os/file.go&lt;/code&gt; , using comment as follows.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight"&gt;&lt;pre class="highlight go"&gt;&lt;code&gt;&lt;span class="c"&gt;// Deprecated: Use io.SeekStart, io.SeekCurrent, and io.SeekEnd.&lt;/span&gt;
&lt;span class="k"&gt;const&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="n"&gt;SEEK_SET&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;0&lt;/span&gt; &lt;span class="c"&gt;// seek relative to the origin of the file&lt;/span&gt;
    &lt;span class="n"&gt;SEEK_CUR&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;1&lt;/span&gt; &lt;span class="c"&gt;// seek relative to the current offset&lt;/span&gt;
    &lt;span class="n"&gt;SEEK_END&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="m"&gt;2&lt;/span&gt; &lt;span class="c"&gt;// seek relative to the end&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt; 
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;So we should follow this rule in our libraries. &lt;/p&gt;

&lt;p&gt;But if you follow this rule, deprecated functions show in Go doc now(&lt;a href="https://github.com/golang/go/issues/17056"&gt;Related discussion&lt;/a&gt;).&lt;br&gt;
Also, golint does not check about deprecated comments(&lt;a href="https://github.com/golang/lint/issues/238"&gt;Related discussion&lt;/a&gt;).&lt;br&gt;
As such, go official tools does not have particular behavior for deprecated comments.  &lt;/p&gt;
&lt;h2&gt;
  
  
  Using &lt;code&gt;staticcheck&lt;/code&gt; for check
&lt;/h2&gt;

&lt;p&gt;&lt;a href="https://github.com/dominikh/go-tools/tree/master/cmd/staticcheck"&gt;staticcheck&lt;/a&gt; in &lt;a href="https://github.com/dominikh/go-tools"&gt;go-tools&lt;/a&gt; can check deprecated things. &lt;/p&gt;

&lt;p&gt;&lt;code&gt;staticcheck&lt;/code&gt; reports as follows if using deprecated things.&lt;br&gt;
&lt;/p&gt;

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

&lt;span class="k"&gt;import&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="s"&gt;"net/http/httputil"&lt;/span&gt;
&lt;span class="p"&gt;)&lt;/span&gt;

&lt;span class="k"&gt;func&lt;/span&gt; &lt;span class="n"&gt;main&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="n"&gt;httputil&lt;/span&gt;&lt;span class="o"&gt;.&lt;/span&gt;&lt;span class="n"&gt;NewClientConn&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="no"&gt;nil&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;





&lt;div class="highlight"&gt;&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nv"&gt;$ &lt;/span&gt;staticcheck main.go
deprecated.go:8:2: httputil.NewClientConn is deprecated: Use the Client or Transport &lt;span class="k"&gt;in &lt;/span&gt;package net/http instead.  &lt;span class="o"&gt;(&lt;/span&gt;SA1019&lt;span class="o"&gt;)&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;



&lt;p&gt;&lt;code&gt;staticcheck&lt;/code&gt; shows comments as it is behinds &lt;code&gt;Deprecated:&lt;/code&gt;. Using this in CI is good. &lt;/p&gt;

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

&lt;ul&gt;
&lt;li&gt;Using &lt;code&gt;Deprecated:&lt;/code&gt;comment for deprecated things. &lt;/li&gt;
&lt;li&gt;Check to deprecated things with &lt;code&gt;staticcheck&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

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