List of Lint - text.Baldanders.info
tag:text.Baldanders.info,2022-07-24:/tags
2022-07-24T21:24:01+09:00
帰ってきた「しっぽのさきっちょ」
https://text.baldanders.info/images/avatar.jpg
https://text.baldanders.info/images/avatar.jpg
strings.Title 関数は非推奨になった
tag:text.Baldanders.info,2022-07-24:/golang/deprecated-strings-title/
2022-07-24T12:24:01+00:00
2022-07-24T22:58:28+00:00
lint は用法・用量を守って正しく使いましょう
Spiegel
https://baldanders.info/profile/
<p>たとえば,以下のコードがあるとする。</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">"fmt"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"strings"</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">msgs</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="s">"hello, world!"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"HELLO, WORLD!"</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">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">msg</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">msgs</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s">"->"</span><span class="p">,</span> <span class="nx">strings</span><span class="p">.</span><span class="nf">Title</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="p">}</span>
</span></span></code></pre></div><p>これを実行すると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample1.go
</span></span><span class="line"><span class="cl">hello, world! -> Hello, World!
</span></span><span class="line"><span class="cl">HELLO, WORLD! -> HELLO, WORLD!
</span></span></code></pre></div><p>と単語の先頭が大文字に変換される。</p>
<p>この <a href="https://pkg.go.dev/strings" title="strings package - strings - Go Packages"><code>strings</code></a><code>.Title()</code> 関数について <a href="https://go.dev/">Go</a> 1.18 から</p>
<figure lang="en">
<blockquote>The <code>Title</code> function is now deprecated. It doesn’t handle Unicode punctuation and language-specific capitalization rules, and is superseded by the <a href="https://golang.org/x/text/cases"><code>golang.org/x/text/cases</code></a> package.</blockquote>
<figcaption><div>via <q><a href="https://go.dev/doc/go1.18">Go 1.18 Release Notes - The Go Programming Language</a></q></div></figcaption>
</figure>
<p>という感じに非推奨になった。
なお,このコードを <a href="https://golangci-lint.run/">golangci-lint</a> にかけると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ golangci-lint run
</span></span><span class="line"><span class="cl">sample1.go:14:26: SA1019: strings.Title has been deprecated since Go 1.18 and an alternative has been available since Go 1.0: The rule Title uses for word boundaries does not handle Unicode punctuation properly. Use golang.org/x/text/cases instead. (staticcheck)
</span></span><span class="line"><span class="cl"> fmt.Println(msg, "->", strings.Title(msg))
</span></span><span class="line"><span class="cl"> ^
</span></span></code></pre></div><p>と言う感じに警告を出してくれる。
つか,この警告で気がついたんだけどね。
相変わらず lint に叱られっぱなしである <code>orz</code></p>
<p>ちなみに似た関数名に <a href="https://pkg.go.dev/strings" title="strings package - strings - Go Packages"><code>strings</code></a><code>.ToTitle()</code> というのがあるが,これを使うと</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample1b.go
</span></span><span class="line"><span class="cl">hello, world! -> HELLO, WORLD!
</span></span><span class="line"><span class="cl">HELLO, WORLD! -> HELLO, WORLD!
</span></span></code></pre></div><p>という感じに全部大文字になる。
これって <a href="https://pkg.go.dev/strings" title="strings package - strings - Go Packages"><code>strings</code></a><code>.ToUpper()</code> と何が違うんか分からん(笑)</p>
<p>さて, <a href="https://pkg.go.dev/strings" title="strings package - strings - Go Packages"><code>strings</code></a><code>.Title()</code> 関数を使う代わりに <a href="https://pkg.go.dev/golang.org/x/text/cases" title="cases package - golang.org/x/text/cases - Go Packages"><code>golang.org/x/text/cases</code></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="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">"fmt"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"golang.org/x/text/cases"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"golang.org/x/text/language"</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">msgs</span> <span class="o">:=</span> <span class="p">[]</span><span class="kt">string</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="s">"hello, world!"</span><span class="p">,</span>
</span></span><span class="line"><span class="cl"> <span class="s">"HELLO, WORLD!"</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">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">msg</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">msgs</span> <span class="p">{</span>
</span></span><span class="line hl"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s">"->"</span><span class="p">,</span> <span class="nx">cases</span><span class="p">.</span><span class="nf">Title</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">Und</span><span class="p">).</span><span class="nf">String</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="p">}</span>
</span></span></code></pre></div><p>これを実行すると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample2.go
</span></span><span class="line"><span class="cl">hello, world! -> Hello, World!
</span></span><span class="line"><span class="cl">HELLO, WORLD! -> Hello, World!
</span></span></code></pre></div><p>おっと! 単語の2文字目以降が違うか。
じゃぁ,オプションをつけて</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">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s">"->"</span><span class="p">,</span> <span class="nx">cases</span><span class="p">.</span><span class="nf">Title</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">Und</span><span class="p">,</span> <span class="nx">cases</span><span class="p">.</span><span class="nx">NoLower</span><span class="p">).</span><span class="nf">String</span><span class="p">(</span><span class="nx">msg</span><span class="p">))</span>
</span></span></code></pre></div><p>とすればいいのかな。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample2b.go
</span></span><span class="line"><span class="cl">hello, world! -> Hello, World!
</span></span><span class="line"><span class="cl">HELLO, WORLD! -> HELLO, WORLD!
</span></span></code></pre></div><p>よーし,うむうむ,よーし。</p>
<p><a href="https://pkg.go.dev/golang.org/x/text/language" title="language package - golang.org/x/text/language - Go Packages"><code>language</code></a><code>.Und</code> の部分は特定の言語(<a href="https://pkg.go.dev/golang.org/x/text/language" title="language package - golang.org/x/text/language - Go Packages"><code>language</code></a><code>.Japanese</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="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">"fmt"</span>
</span></span><span class="line"><span class="cl">
</span></span><span class="line"><span class="cl"> <span class="s">"golang.org/x/text/cases"</span>
</span></span><span class="line"><span class="cl"> <span class="s">"golang.org/x/text/language"</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">msg</span> <span class="o">:=</span> <span class="s">"'n"</span>
</span></span><span class="line"><span class="cl"> <span class="nx">casers</span> <span class="o">:=</span> <span class="p">[]</span><span class="nx">cases</span><span class="p">.</span><span class="nx">Caser</span><span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">cases</span><span class="p">.</span><span class="nf">Title</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">English</span><span class="p">),</span>
</span></span><span class="line"><span class="cl"> <span class="nx">cases</span><span class="p">.</span><span class="nf">Title</span><span class="p">(</span><span class="nx">language</span><span class="p">.</span><span class="nx">Dutch</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">for</span> <span class="nx">_</span><span class="p">,</span> <span class="nx">caser</span> <span class="o">:=</span> <span class="k">range</span> <span class="nx">casers</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="nx">fmt</span><span class="p">.</span><span class="nf">Println</span><span class="p">(</span><span class="nx">msg</span><span class="p">,</span> <span class="s">"->"</span><span class="p">,</span> <span class="nx">caser</span><span class="p">.</span><span class="nf">String</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="p">}</span>
</span></span></code></pre></div><p>これを実行すると</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ go run sample3.go
</span></span><span class="line"><span class="cl">'n -> 'N
</span></span><span class="line"><span class="cl">'n -> 'n
</span></span></code></pre></div><p>という感じに言語によって違いが出るようだ?</p>
<h2>Lint は用法・用量を守って正しく使いましょう</h2>
<p>話は変わるが,「失敗」には大きく2つある。
「受動的失敗」と「能動的失敗」だ。
このフレーズは Bruce Schneier さんの『<a href="https://www.amazon.co.jp/dp/4822283100?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">セキュリティはなぜやぶられたのか(Beyond Fear)</a>』にセキュリティ用語として出てくる。</p>
<figure>
<blockquote>セキュリティシステムの問題は大きく分けてふたつのパターンがある。
ひとつ目は攻撃に対する防御が失敗するもの。
(中略)
とるべき対策が実行されない受動的な失敗である。
ふたつ目は間違ったときに対策を実行して防御が失敗するもの。
(中略)
とるべき対策を実行したがゆえの能動的な失敗である。</blockquote>
<figcaption><div><q><a href="https://www.amazon.co.jp/dp/4822283100?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">『セキュリティはなぜやぶられたのか』p.77</a></q>より</div></figcaption>
</figure>
<p>受動的失敗は批判の対象になりやすいが,受動的失敗を恐れるあまり能動的失敗に陥るというのもありがちなパターンである。</p>
<p>いや Twitter の TL で <a href="https://golangci-lint.run/">golangci-lint</a> をフルオプションで起動して山ほど警告が出てきても平気みたいな記述を見かけたので。
これって典型的な能動的失敗だよなぁ。
オオカミが来た!</p>
<p>もとより lint のような静的コード解析は万能ではない。
なれば,より気にすべきなのは受動的失敗より能動的失敗である。</p>
<p><a href="https://golangci-lint.run/">golangci-lint</a> はオプション無しでもかなりの部分を網羅できる。
せいぜい gosec を追加するくらい。
まずはこれで<strong>警告が出ない</strong>ことを目指した上で,プロダクトによって過不足があれば少しずつ調整していけばいいのだ。</p>
<p>たとえば,拙作の <a href="https://github.com/goark/gnkf" title="goark/gnkf: Network Kanji Filter by Golang">gnkf</a> は MD5 や SHA-1 のハッシュ値を出力する機能があるが gosec を含めて lint をかけると「弱いハッシュ関数を使うな(←超意訳)」みたいな警告が出てしまう。
そこで</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ golangci-lint run --enable gosec --exclude "G501|G505" ./...
</span></span></code></pre></div><p>のようにチェック対象を調整している。
仕事で使うならメンバ間で <code>.golangci.yaml</code> 等を使って設定を合わせておけばいいだろう。</p>
<p>lint は用法・用量を守って正しく使いましょう。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://zenn.dev/tenntenn/books/d168faebb1a739">逆引き Goによる静的解析</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4822283100?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51-pZ52JsUL._SL160_.jpg" width="107" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4822283100?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">セキュリティはなぜやぶられたのか</a></dt>
<dd>ブルース・シュナイアー (著), 井口 耕二 (翻訳)</dd>
<dd>日経BP 2007-02-15</dd>
<dd>単行本</dd>
<dd>4822283100 (ASIN), 9784822283100 (EAN), 4822283100 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">原書のタイトルが “<a href="https://www.amazon.co.jp/dp/B000PY3NB4?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">Beyond Fear: Thinking Sensibly About Security in an Uncertain World</a>” なのに対して日本語タイトルがどうしようもなくヘボいが中身は名著。とりあえず読んどきなはれ。ゼロ年代当時 9.11 およびその後の米国のセキュリティ政策と深く関連している内容なので,そのへんを加味して読むとよい。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2019-02-11">2019-02-11</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- セキュリティはなぜやぶられたのか -->
Go 1.18 と Generics と Linter
tag:text.Baldanders.info,2022-03-19:/remark/2022/03/linter-troubles-in-go-1_18/
2022-03-19T06:16:40+00:00
2022-03-19T06:29:17+00:00
Go 1.18 に組み込まれた Generics と既存の lint の間でトラブルが続出しているらしい。
Spiegel
https://baldanders.info/profile/
<p>予測して然るべきであったが <a href="https://go.dev/">Go</a> 1.18 に組み込まれた Generics と既存の linter の間でトラブルが続出しているらしい。</p>
<p>私も大変お世話になっている <a href="https://go.dev/">Go</a> の代表的な総合 linter である <a href="https://github.com/golangci/golangci-lint/" title="golangci/golangci-lint: Fast linters Runner for Go">golangci-lint</a> は <a href="https://github.com/golangci/golangci-lint/releases/tag/v1.45.0" title="Release v1.45.0 · golangci/golangci-lint">v1.45</a> で暫定的な対応を行ったようだ。</p>
<figure lang="en">
<blockquote><p>So I added a new configuration option inside the run section.<br>
We will not have to remove this option in the future because we will be able to use it for some linters that have a Go version option.</p>
<p>An example:</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">go</span><span class="p">:</span><span class="w"> </span><span class="m">1.18</span><span class="w">
</span></span></span></code></pre></div><p>By default, the supported Go version will be go1.17 because it allows us to run all our tests without a huge rewrite.</p>
<p>If you set the version to go1.18, the following linters will be inactive:</p>
<ul>
<li><code>bodyclose</code></li>
<li><code>contextcheck</code></li>
<li><code>gosimple</code></li>
<li><code>nilerr</code></li>
<li><code>noctx</code></li>
<li><code>rowserrcheck</code></li>
<li><code>sqlclosecheck</code></li>
<li><code>staticcheck</code></li>
<li><code>stylecheck</code></li>
<li><code>tparallel</code></li>
<li><code>unparam</code></li>
<li><code>unused</code></li>
<li><code>wastedassign</code></li>
</ul>
</blockquote>
<figcaption><div>via <q><a href="https://github.com/golangci/golangci-lint/issues/2649#issuecomment-1070528726">Support of go1.18 · Issue #2649 · golangci/golangci-lint</a></q></div></figcaption>
</figure>
<p>この説明にあるように <code>.golangci.yaml</code> ファイルに</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">go</span><span class="p">:</span><span class="w"> </span><span class="m">1.18</span><span class="w">
</span></span></span></code></pre></div><p>の記述を入れることで <a href="https://go.dev/">Go</a> 1.18 に対応していない linter を無効にしてくれるようだ。
あとは各 lint パッケージが 1.18 に対応してくれることを気長に待つしかないか。</p>
<p>なお Generics の機能を使わないのなら今回の件は気にしなくてよい(笑)</p>
<p>あと <a href="https://github.com/golangci/golangci-lint-action" title="golangci/golangci-lint-action: Official GitHub action for golangci-lint from its authors">golangci-lint-action</a> もいつの間にか v3 に上がってるな。
見落としてたかなぁ。
この辺はおいおい検証しよう。</p>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
MISRA-C の思ひ出(または「守られないルールはルール自体に問題がある」)
tag:text.Baldanders.info,2021-04-25:/remark/2021/04/making-rule/
2021-04-25T02:35:57+00:00
2021-04-25T02:36:51+00:00
ルール・メイキングは難しい
Spiegel
https://baldanders.info/profile/
<h2>オンライン開催お疲れさまでした</h2>
<p>2021-04-21 に開催された <a href="https://gocon.connpass.com/event/208896/">Go Conference 2021 Spring</a> は初のオンラインだったそうで,週末の土曜日ということもあって,出不精で人見知りな私でも気軽に参加できたのがありがたかった。
(リアルタイム視聴も含めて)動画や音声のコンテンツはまとまった時間で拘束されてしまうのであまり好きではないのだが,たまにはこういうものに参加するのもよろしかろう。</p>
<p>そのなかのひとつである</p>
<ul>
<li><a href="https://speakerdeck.com/lmt_swallow/lets-build-security-guardrails-for-your-go-programs" title="Go をセキュアに書き進めるための「ガードレール」を整備しよう / Let's Build Security Guardrails For Your Go Programs! - Speaker Deck">Go をセキュアに書き進めるための「ガードレール」を整備しよう / Let’s Build Security Guardrails For Your Go Programs! - Speaker Deck</a></li>
</ul>
<p>は興味深く視聴させてもらった。
特に <a href="https://github.com/quasilyte/go-ruleguard" title="quasilyte/go-ruleguard: Define and run pattern-based custom linting rules.">go-ruleguard</a> は面白そうだ。
個人でも使う機会があるかもしれない。</p>
<p>ちなみに,<a href="https://speakerdeck.com/lmt_swallow/lets-build-security-guardrails-for-your-go-programs" title="Go をセキュアに書き進めるための「ガードレール」を整備しよう / Let's Build Security Guardrails For Your Go Programs! - Speaker Deck">スライド</a>にも書かれているが, <a href="https://github.com/securego/gosec" title="securego/gosec: Golang security checker">gosec</a> は <a href="https://golangci-lint.run/">golangci-lint</a> にも組み込まれているので</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">$ golangci-lint run --enable gosec ./...
</span></span></code></pre></div><p>といった感じに使うことができる。</p>
<h2>MISRA-C の思ひ出</h2>
<p>この発表を視聴しながら思い出していたのは大昔に車載系のプロジェクトに参加したときのことだ。
あのときはアセンブラでベクタテーブルからゴリゴリ書いてたよなぁ(遠い目)</p>
<p>今は違うと思うが,当時は MISRA-C というガイドラインがあって,これが車載系における事実上の C 言語コーディング基準(criteria)になっていた。</p>
<p>詳細は割愛するが, MISRA-C には127個のルールがあって「必要(Required)」と「推奨(Advisory)」のいずれかに分類されている。
このうち「必要」ルールは強制的に課せられるルールで,このルールからの逸脱(deviation)を許容する場合には,手続きを踏んで文書化と承認を行わなければならない。
各ルールにはルールの詳細(何故そのルールが必要か)と逸脱可否の判断基準とサンプルコードが載っているので,それを参考に逸脱の可否を判定する。</p>
<p>MISRA-C が定めるルール自体は合理的な内容なのだが,127個ものルールを机上でチェックするのは不毛なので MISRA-C 対応の lint ツールを使うことになる(当時はこれがバカ高くてねぇ)。
で,当然ながら lint ツールは製品の差別化のために MISRA-C 以外のルールもチェックできるようになっていて,最終的に数百ものルールをチェックすることになる。</p>
<h2>守られないルールはルール自体に問題がある</h2>
<p>問題は lint を実施した結果,大量の警告が出た場合である。
あるルールについて大量の逸脱が発生する理由は大きく2つある。</p>
<ol>
<li>プログラム設計が根本的に間違っている</li>
<li>ルールが間違っている</li>
</ol>
<p>プログラマのスキルによるかもしれないが,経験上こういうときに前者が理由であることはほとんどない。
なので,まずは「ルールが間違っている」のではないかと疑ってみるのが定石である。</p>
<p>基本的に「ルールは守られるべきもの」であるが,ルールもまた人間が考えたものであり,間違っている可能性を常に考慮すべきである。
何故なら人間は間違いを犯す生き物なのだから。</p>
<p>私は「悪法も法」という考え方には与しない。
「悪法は悪法」であり正すべきだ。
そして「悪法」の判断基準のひとつが「守られないルールはルール自体に問題がある」である。
ルールもリファクタリングの対象となる「コード」なのだ。</p>
<p>最初に挙げた<a href="https://speakerdeck.com/lmt_swallow/lets-build-security-guardrails-for-your-go-programs" title="Go をセキュアに書き進めるための「ガードレール」を整備しよう / Let's Build Security Guardrails For Your Go Programs! - Speaker Deck">発表</a>では <a href="https://github.com/reviewdog/reviewdog" title="reviewdog/reviewdog: 🐶 Automated code review tool integrated with any code analysis tools regardless of programming language">reviewdog</a> を使って変更部分のみチェックする方法が紹介されていたが, <a href="https://github.com/reviewdog/reviewdog" title="reviewdog/reviewdog: 🐶 Automated code review tool integrated with any code analysis tools regardless of programming language">reviewdog</a> を常用するのは個人的にお勧めできない。
これが常態化すると「動いてるコードは触るな」という方向に行きがちで,それによってリファクタリングの機会を失うこととなり,最終的に<a href="https://text.baldanders.info/remark/2020/12/technical-debt-and-hacker/" title="技術的負債とハッカー">技術的負債</a>の返済が遅れることになる。
リファクタリングに厚いのが Go の持ち味なので,これを抑圧するような運用は避けるべきだろう。</p>
<p>ことほど左様にルール・メイキングというのは難しいのである。
できるなら,煩わしいことは機械に任せて楽しくコードを書きたいものである。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://text.baldanders.info/golang/using-golangci-lint-action/">golangci-lint を GitHub Actions で使う</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4542503461?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51CAFNAdZPL._SL160_.jpg" width="113" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4542503461?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド</a></dt>
<dd>MISRA‐C研究会 (編集)</dd>
<dd>日本規格協会 2006-10-01</dd>
<dd>単行本</dd>
<dd>4542503461 (ASIN), 9784542503465 (EAN), 4542503461 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">私が持っているのはこれよりひとつ古い版だが,まぁいいか。むかし,車載用の組み込みエンジニアをやっていた頃は必読書として読まされました。今はもっと包括的な内容のものがあるはず。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2019-02-06">2019-02-06</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 組込み開発者におくるMISRA‐C:2004 -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B01CYDGUV8?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/31Q2jh+5SgL._SL160_.jpg" width="113" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B01CYDGUV8?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">CODE VERSION 2.0</a></dt>
<dd>ローレンス・レッシグ (著), 山形浩生 (翻訳)</dd>
<dd>翔泳社 2007-12-19 (Release 2016-03-14)</dd>
<dd>Kindle版</dd>
<dd>B01CYDGUV8 (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">前著『CODE』改訂版。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2018-11-17">2018-11-17</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- CODE VERSION 2.0 -->
golangci-lint を GitHub Actions で使う
tag:text.Baldanders.info,2020-09-29:/golang/using-golangci-lint-action/
2020-09-29T02:20:19+00:00
2022-04-24T09:34:08+00:00
これで pull request 時に golangci-lint が走る。
Spiegel
https://baldanders.info/profile/
<p><a href="https://golangci-lint.run/">golangci-lint</a> は <code>go vet</code> をはじめ複数の lint を集約して結果を表示してくれる優れものである。
かつては GolangCI.com で <a href="https://github.com/">GitHub</a> と連携できていたのだが,<a href="https://medium.com/golangci/golangci-com-is-closing-d1fc1bd30e0e" title="GolangCI.com is closing. Dear customers of GolangCI.com, | by Denis Isaev | golangci | Medium">2020年4月でサービスが停止</a>してしまい,寂しい限り。</p>
<p>と思っていたのだが,いつの間にか公式の <a href="https://github.com/">GitHub</a> Actions が用意されていた。
気付かなんだよ。
不覚。</p>
<ul>
<li><a href="https://github.com/golangci/golangci-lint-action">golangci/golangci-lint-action: Official GitHub action for golangci-lint from it’s authors</a></li>
</ul>
<p>使い方は簡単。
リポジトリの <code>.github/workflows/</code> ディレクトリに YAML ファイル(例えば <code>lint.yml</code>)を置き,以下のように記述する。</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">name</span><span class="p">:</span><span class="w"> </span><span class="l">golangci-lint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">on</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">push</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">tags</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">v*</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">branches</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="l">master</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">pull_request</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"></span><span class="nt">jobs</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">golangci</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">strategy</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">matrix</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">go-version</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="m">1.15</span><span class="l">.x]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">os</span><span class="p">:</span><span class="w"> </span><span class="p">[</span><span class="l">ubuntu-latest, macos-latest, windows-latest]</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">lint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">runs-on</span><span class="p">:</span><span class="w"> </span><span class="l">${{ matrix.os }}</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">steps</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">actions/checkout@v2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span>- <span class="nt">name</span><span class="p">:</span><span class="w"> </span><span class="l">golangci-lint</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">uses</span><span class="p">:</span><span class="w"> </span><span class="l">golangci/golangci-lint-action@v2</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">with</span><span class="p">:</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># Required: the version of golangci-lint is required and must be specified without patch version: we always use the latest patch version.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="nt">version</span><span class="p">:</span><span class="w"> </span><span class="l">v1.31</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="c"># Optional: working directory, useful for monorepos</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># working-directory: somedir</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="c"># Optional: golangci-lint command line arguments.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># args: --issues-exit-code=0</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="c"># Optional: show only new issues if it's a pull request. The default value is `false`.</span><span class="w">
</span></span></span><span class="line"><span class="cl"><span class="w"> </span><span class="c"># only-new-issues: true</span><span class="w">
</span></span></span></code></pre></div><p>また,リポジトリ直下の <code>.gitattributes</code> ファイルに以下の記述を追加する。</p>
<div class="highlight"><pre tabindex="0" class="chroma"><code class="language-text" data-lang="text"><span class="line"><span class="cl">*.go text eol=lf
</span></span></code></pre></div><p>これで pull request 時, <code>master</code> ブランチ<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup> への push 時,およびバージョンタグを打った際に <a href="https://golangci-lint.run/">golangci-lint</a> が走る。
<a href="https://golangci-lint.run/">golangci-lint</a> は <code>matrix</code> の組み合わせで並列処理されるようだ。</p>
<figure style='margin:0 auto;text-align:center;'><a href="./reviews-in-pr.png"><img src="./reviews-in-pr.png" srcset="./reviews-in-pr.png 867w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>よーし,うむうむ,よーし。</p>
<p>まぁ,プラットフォーム依存のコードでもない限り <a href="https://go.dev/">Go</a> 最新バージョンの <code>ubuntu-latest</code> だけでいいと思うけどね。</p>
<h2>ブックマーク</h2>
<ul>
<li>
<p><a href="https://github.com/golangci/golangci-lint">golangci/golangci-lint: Fast linters Runner for Go</a></p>
</li>
<li>
<p><a href="https://zenn.dev/ikawaha/articles/57384e8fc69c7b057f7f">reviewdog-golangci-lint を使う</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/golang/donot-sleep-through-life/">golangci-lint に叱られる</a></p>
</li>
<li>
<p><a href="https://text.baldanders.info/golang/update-github-actions/">CI 用の GitHub Actions が諸々アップデートされていた</a></p>
</li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>2020年10月から <a href="https://text.baldanders.info/remark/2020/08/renaming-default-branch-name-in-github-repositries/" title="GitHub リポジトリの既定ブランチ名が main になるらしい">GitHub の新規リポジトリの既定ブランチ名が <code>main</code> になるらしい</a>。ご注意を。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
GolangCI でコード・レビューを自動化する
tag:text.Baldanders.info,2019-12-15:/golang/code-review-with-golangci/
2019-12-15T05:05:25+00:00
2021-12-04T02:40:05+00:00
リポジトリ全体をチェックしてくれるレビュー・サービスの存在はありがたい。
Spiegel
https://baldanders.info/profile/
<div class="box"><p>この記事で紹介した <a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> のレビュー・サービスは 2020-04-15 で終了するらしい。</p>
<ul>
<li><a href="https://medium.com/golangci/golangci-com-is-closing-d1fc1bd30e0e">GolangCI.com is closing - golangci - Medium</a></li>
</ul>
<p>まぁ <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>自体がもっと普及しないと営利サービスとしては難しいのかもね。
残念ではあるが lint ツール自体は公開を続けるそうな。
うんうん,よかったよかった。</p>
</div>
<p>以前「<a href="https://text.baldanders.info/golang/donot-sleep-through-life/">golangci-lint に叱られる</a>」で</p>
<blockquote>
<p><q><a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> も気になるが,それはまたいつか</q></p>
</blockquote>
<p>と書いたが,今回はその話。</p>
<p><a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> は <a href="https://github.com/" title="The world’s leading software development platform · GitHub">GitHub</a> と連携して機能するコード・レビュー・サービスで, <a href="https://github.com/" title="The world’s leading software development platform · GitHub">GitHub</a> 上のリポジトリにある <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>コードに lint をかけて結果を報告してくれる。
Pull request とも連携してレビュー結果を上げてくれるので,レビューにかかる労力をかなり引き下げることができる<sup id="fnref:1"><a href="#fn:1" class="footnote-ref" role="doc-noteref">1</a></sup>。</p>
<p>サインアップは <a href="https://github.com/" title="The world’s leading software development platform · GitHub">GitHub</a> アカウントで行うことができる。
サインアップに成功したらリポジトリ一覧画面に行けるようになる<sup id="fnref:2"><a href="#fn:2" class="footnote-ref" role="doc-noteref">2</a></sup>。</p>
<figure style='margin:0 auto;text-align:center;'><a href="./list-of-reps.jpg"><img src="./list-of-reps.jpg" srcset="./list-of-reps.jpg 850w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>連携したいリポジトリに <code>[Connect]</code> するとレビューを開始するのだが,レビュー結果が表示されるまで結構時間がかかるみたい。
実は随分前に <a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> に登録していくつかのパッケージと連携させていたのだが,なかなか処理が終わらないので,そのまま綺麗サッパリ忘れ去っていたのだった(笑)</p>
<p>レビューが終わったリポジトリの <code>[Report]</code> を開くとこんな感じの画面になる。
これは問題がなかったリポジトリの場合:</p>
<figure style='margin:0 auto;text-align:center;'><a href="./result-review-no-error.jpg"><img src="./result-review-no-error.jpg" srcset="./result-review-no-error.jpg 850w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>こっちは問題が発見されたリポジトリ:</p>
<figure style='margin:0 auto;text-align:center;'><a href="./result-review-error.jpg"><img src="./result-review-error.jpg" srcset="./result-review-error.jpg 850w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>このレポート結果を基にコードを修正する。
当然ながら master ブランチ上で作業をしないこと。</p>
<p>修正を commit & push し,修正を行ったブランチから pull request をかける。
<a href="https://github.com/" title="The world’s leading software development platform · GitHub">GitHub</a> 側は pull request したコードに対して連携しているサービスを呼び出して事前チェックを行う。
チェックにパスすればこんな感じになる。</p>
<figure style='margin:0 auto;text-align:center;'><a href="./pull-request.jpg"><img src="./pull-request.jpg" srcset="./pull-request.jpg 850w" sizes="(min-width:600px) 500px, 80vw" alt="" loading="lazy"></a></figure>
<p>問題があれば “Details” で問題箇所が示されるので,修正を行って再度 commit & push する。</p>
<p><a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> には<a href="https://github.com/golangci/golangci-lint" title="golangci/golangci-lint: Linters Runner for Go. 5x faster than gometalinter. Nice colored output. Can report only new issues. Fewer false-positives. Yaml/toml config.">コマンドライン・ツール</a>も用意されていて IDE やテキストエディタなどとも連携可能なのだが<sup id="fnref:3"><a href="#fn:3" class="footnote-ref" role="doc-noteref">3</a></sup>,どうしても見落としがあるみたいで,リポジトリ全体をチェックしてくれるレビュー・サービスの存在はありがたい。</p>
<p>さて,他のパッケージも修正するか。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://dev.classmethod.jp/go/golangci/">無料で使える Go 言語の CI サービス『GolangCI』を使ってみる | Developers.IO</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4542503461?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51CAFNAdZPL._SL160_.jpg" width="113" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4542503461?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド</a></dt>
<dd>MISRA‐C研究会 (編集)</dd>
<dd>日本規格協会 2006-10-01</dd>
<dd>単行本</dd>
<dd>4542503461 (ASIN), 9784542503465 (EAN), 4542503461 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">私が持っているのはこれよりひとつ古い版だが,まぁいいか。むかし,車載用の組み込みエンジニアをやっていた頃は必読書として読まされました。今はもっと包括的な内容のものがあるはず。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2019-02-06">2019-02-06</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 組込み開発者におくるMISRA‐C:2004 -->
<div class="footnotes" role="doc-endnotes">
<hr>
<ol>
<li id="fn:1">
<p>とはいえ <a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> がチェックしてくれるのは lint レベルのコード・チェックなので,ビジネスロジック等の妥当性は人間が判断する必要がある。言い方を変えれば <a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> で lint レベルのチェックを事前に行っておけば,人間はビジネスロジック等のチェックに専念することができる。 <a href="#fnref:1" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:2">
<p>既定では公開リポジトリのみが対象となる。お金を払えばプライベート・リポジトリもチェックできるらしいが試していない。 <a href="#fnref:2" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
<li id="fn:3">
<p><a href="https://atom.io/">ATOM</a> エディタの場合は <a href="https://atom.io/packages/go-plus">go-plus</a> パッケージで Linter に <a href="https://github.com/golangci/golangci-lint" title="golangci/golangci-lint: Linters Runner for Go. 5x faster than gometalinter. Nice colored output. Can report only new issues. Fewer false-positives. Yaml/toml config.">golangci-lint</a> を指定できる。 <a href="#fnref:3" class="footnote-backref" role="doc-backlink">↩︎</a></p>
</li>
</ol>
</div>
golangci-lint に叱られる
tag:text.Baldanders.info,2019-02-06:/golang/donot-sleep-through-life/
2019-02-06T14:15:43+00:00
2021-08-12T21:22:05+00:00
そんなことまで知っている golangci-lint は偉いねぇ。
Spiegel
https://baldanders.info/profile/
<p>私は <a href="https://golang.org/" title="The Go Programming Language">Go 言語</a>コードを <a href="https://atom.io/" title="Atom">ATOM</a> エディタおよび <a href="https://atom.io/packages/go-plus">go-plus</a> パッケージで書いているのだが,最近の <a href="https://atom.io/packages/go-plus">go-plus</a> は lint に以下のツールを選択できるようだ。</p>
<ul>
<li><a href="https://github.com/alecthomas/gometalinter" title="alecthomas/gometalinter: Concurrently run Go lint tools and normalise their output">gometalinter</a></li>
<li><a href="https://github.com/golangci/golangci-lint" title="golangci/golangci-lint: Linters Runner for Go. 5x faster than gometalinter. Nice colored output. Can report only new issues. Fewer false-positives. Yaml/toml config.">golangci-lint</a></li>
<li><a href="https://github.com/mgechev/revive" title="mgechev/revive: 🔥 ~6x faster, stricter, configurable, extensible, and beautiful drop-in replacement for golint.">revive</a></li>
</ul>
<p>特に <a href="https://github.com/golangci/golangci-lint" title="golangci/golangci-lint: Linters Runner for Go. 5x faster than gometalinter. Nice colored output. Can report only new issues. Fewer false-positives. Yaml/toml config.">golangci-lint</a> は <a href="https://github.com/alecthomas/gometalinter" title="alecthomas/gometalinter: Concurrently run Go lint tools and normalise their output">gometalinter</a> より5倍も速いと豪語してるので,こちらを試してみることにした。
<a href="https://golangci.com/" title="Automated code review for Go">GolangCI</a> も気になるが,それはまたいつか。</p>
<p>いやぁ,最近の lint は賢いんだね。
特に古いコードのまま放置している部分についてどえら叱られたですよ。
ボーっと生きててすみません(笑)</p>
<h2>error を無視すんな</h2>
<p>例えば <a href="https://golang.org/pkg/io/" title="io - The Go Programming Language"><code>io</code></a><code>.Reader</code> から <a href="https://golang.org/pkg/io/" title="io - The Go Programming Language"><code>io</code></a><code>.Writer</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="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">writer</span><span class="p">,</span> <span class="nx">reader</span><span class="p">)</span>
</span></span></code></pre></div><p>とか書くことがあるが <a href="https://github.com/golangci/golangci-lint" title="golangci/golangci-lint: Linters Runner for Go. 5x faster than gometalinter. Nice colored output. Can report only new issues. Fewer false-positives. Yaml/toml config.">golangci-lint</a> にかけたら「返り値の error を無視すんなや」って叱られた。
ちゃんと書くなら</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="nx">_</span><span class="p">,</span> <span class="nx">err</span> <span class="o">:=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">writer</span><span class="p">,</span> <span class="nx">reader</span><span class="p">);</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="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>とかすべき,ということだろう。
明示的に返り値の error を無視するなら</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">_</span><span class="p">,</span> <span class="nx">_</span> <span class="p">=</span> <span class="nx">io</span><span class="p">.</span><span class="nf">Copy</span><span class="p">(</span><span class="nx">writer</span><span class="p">,</span> <span class="nx">reader</span><span class="p">)</span>
</span></span></code></pre></div><p>などと明示すれば,とりあえず叱られない。
まぁ安直にこう書いてしまうのは問題だけど。</p>
<h2>true は不要</h2>
<p>無限ループについて昔は何となく</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">for</span> <span class="kc">true</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>とか書いていて,またも「true とか要らんけぇ」と叱られた。
正しくは</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">for</span> <span class="p">{</span>
</span></span><span class="line"><span class="cl"> <span class="o">...</span>
</span></span><span class="line"><span class="cl"><span class="p">}</span>
</span></span></code></pre></div><p>でよい。
こういう「若気の至り」なコードがそこかしこに残ってて,黒歴史を見せられてるようでちょっと恥ずかしい。</p>
<h2>SIGNAL のバッファリング</h2>
<p>SIGNAL を channel として登録する際に誤って</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">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Signal</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">signal</span><span class="p">.</span><span class="nf">Notify</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="nx">sig</span><span class="o">...</span><span class="p">)</span>
</span></span></code></pre></div><p>とか書いていて「ちゃんとバッファリングさせろや,ゴラァ」とまたまた叱られた。
正解は</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">ch</span> <span class="o">:=</span> <span class="nb">make</span><span class="p">(</span><span class="kd">chan</span> <span class="nx">os</span><span class="p">.</span><span class="nx">Signal</span><span class="p">,</span> <span class="mi">1</span><span class="p">)</span>
</span></span><span class="line"><span class="cl"><span class="nx">signal</span><span class="p">.</span><span class="nf">Notify</span><span class="p">(</span><span class="nx">ch</span><span class="p">,</span> <span class="nx">sig</span><span class="o">...</span><span class="p">)</span>
</span></span></code></pre></div><p>そんなことまで知っている <a href="https://github.com/golangci/golangci-lint" title="golangci/golangci-lint: Linters Runner for Go. 5x faster than gometalinter. Nice colored output. Can report only new issues. Fewer false-positives. Yaml/toml config.">golangci-lint</a> は偉いねぇ。</p>
<h2>Lint は知見のかたまり</h2>
<p>というわけで過去の恥ずかしいコードが次々と発覚してしまい,公開しているコードのリファクタリングを行っている真っ最中である。
色々やりたいことがあるのに横道に逸れてばっかり。</p>
<p>C 言語で書いてた頃は MISRA-C とかいった「事実上の標準」みたいなのがあって lint ツールとかも(少なくともエンタープライズ向けは)そういったものに準拠したものが色々あった。
Lint ってのはそのプログラミング言語に関する知見のかたまりなので上手に使いこなしていきたいものである。</p>
<h2>ブックマーク</h2>
<ul>
<li><a href="https://mattn.kaoriya.net/software/lang/go/20190205190203.htm">Big Sky :: Lint ツールを Language Server に対応させるコマンド efm-langserver 作った。</a></li>
<li><a href="https://budougumi0617.github.io/2020/09/06/why_signal_notify_want_buffered_channel/">signal.Notifyを使うときは必ずバッファ付きチャネルで利用すること - My External Storage</a></li>
</ul>
<h2>参考図書</h2>
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/416Stewy0NS._SL160_.jpg" width="123" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/B099928SJD?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">プログラミング言語Go</a></dt>
<dd>アラン・ドノバン (著), ブライアン・カーニハン (著), 柴田芳樹 (著)</dd>
<dd>丸善出版 2016-06-20 (Release 2021-07-13)</dd>
<dd>Kindle版</dd>
<dd>B099928SJD (ASIN)</dd>
<dd>評価<abbr class="rating fa-sm" title="5"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i></abbr></dd>
</dl>
<p class="description">Kindle 版出た! 一部内容が古びてしまったが,この本は Go 言語の教科書と言ってもいいだろう。感想は<a href="https://text.baldanders.info/remark/2016/07/go-programming-language/" >こちら</a>。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2021-05-22">2021-05-22</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- プログラミング言語Go -->
<div class="hreview">
<div class="photo"><a href="https://www.amazon.co.jp/dp/4542503461?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1"><img src="https://m.media-amazon.com/images/I/51CAFNAdZPL._SL160_.jpg" width="113" alt="photo"></a></div>
<dl>
<dt class="item"><a class="fn url" href="https://www.amazon.co.jp/dp/4542503461?tag=baldandersinf-22&linkCode=ogi&th=1&psc=1">組込み開発者におくるMISRA‐C:2004―C言語利用の高信頼化ガイド</a></dt>
<dd>MISRA‐C研究会 (編集)</dd>
<dd>日本規格協会 2006-10-01</dd>
<dd>単行本</dd>
<dd>4542503461 (ASIN), 9784542503465 (EAN), 4542503461 (ISBN)</dd>
<dd>評価<abbr class="rating fa-sm" title="4"> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="fas fa-star"></i> <i class="far fa-star"></i></abbr></dd>
</dl>
<p class="description">私が持っているのはこれよりひとつ古い版だが,まぁいいか。むかし,車載用の組み込みエンジニアをやっていた頃は必読書として読まされました。今はもっと包括的な内容のものがあるはず。</p>
<p class="powered-by">reviewed by <a href='#maker' class='reviewer'>Spiegel</a> on <abbr class="dtreviewed" title="2019-02-06">2019-02-06</abbr> (powered by <a href="https://affiliate.amazon.co.jp/assoc_credentials/home">PA-APIv5</a>)</p>
</div> <!-- 組込み開発者におくるMISRA‐C:2004 -->