Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
ゆるやかにgolangci-lintのルールを強くする / Kyoto.go #56
Search
utagawa kiki
December 15, 2024
Programming
2
780
ゆるやかにgolangci-lintのルールを強くする / Kyoto.go #56
Kyoto.go #56
https://kyotogo.connpass.com/event/335437/
utagawa kiki
December 15, 2024
Tweet
Share
More Decks by utagawa kiki
See All by utagawa kiki
君たちはどうコードをレビューする (される) か / 大吉祥寺.pm
utgwkk
21
13k
Dive into gomock / Go Conference 2024
utgwkk
14
5.7k
Goでリフレクションする、その前に / Kansai.go #1
utgwkk
5
2.3k
Go製Webアプリケーションのエラーとの向き合い方大全、あるいはやっぱりスタックトレース欲しいやん / Kyoto.go #50
utgwkk
7
3.7k
ありがとう、create-react-app
utgwkk
4
11k
mockgenによるモック生成を高速化するツール bulkmockgenのご紹介 / Kyoto.go #43
utgwkk
2
2.3k
SPAでもデータをURLでシェアしたい / Kyoto.js 19
utgwkk
2
1.9k
prototype大全 / YAPC::Kyoto 2023
utgwkk
1
4.4k
なんでもPull Requestにする / Kichijoji.pm 31
utgwkk
3
6.3k
Other Decks in Programming
See All in Programming
traP の部内 ISUCON とそれを支えるポータル / PISCON Portal
ikura_hamu
0
130
PHPとAPI Platformで作る本格的なWeb APIアプリケーション(入門編) / phpcon 2024 Intro to API Platform
ttskch
0
360
Flatt Security XSS Challenge 解答・解説
flatt_security
0
590
情報漏洩させないための設計
kubotak
5
1.2k
Beyond ORM
77web
11
1.5k
テストコードのガイドライン 〜作成から運用まで〜
riku929hr
6
1.3k
Kaigi on Railsに初参加したら、その日にLT登壇が決定した件について
tama50505
0
140
QA環境で誰でも自由自在に現在時刻を操って検証できるようにした話
kalibora
1
110
php-conference-japan-2024
tasuku43
0
410
Запуск 1С:УХ в крупном энтерпрайзе: мечта и реальность ПМа
lamodatech
0
870
なまけものオバケたち -PHP 8.4 に入った新機能の紹介-
tanakahisateru
1
140
KMP와 kotlinx.rpc로 서버와 클라이언트 동기화
kwakeuijin
0
270
Featured
See All Featured
Typedesign – Prime Four
hannesfritz
40
2.5k
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
550
Writing Fast Ruby
sferik
628
61k
Being A Developer After 40
akosma
89
590k
Building Your Own Lightsaber
phodgson
104
6.2k
For a Future-Friendly Web
brad_frost
176
9.5k
The MySQL Ecosystem @ GitHub 2015
samlambert
250
12k
YesSQL, Process and Tooling at Scale
rocio
170
14k
We Have a Design System, Now What?
morganepeng
51
7.3k
Adopting Sorbet at Scale
ufuk
74
9.1k
Designing on Purpose - Digital PM Summit 2013
jponch
116
7k
How to Ace a Technical Interview
jacobian
276
23k
Transcript
ゆるやかにgolangci-lint のルールを強くする id:utgwkk / @utgwkk (うたがわきき) 2024/12/15 Kyoto.go #56 オフライン忘年LT会@マネフォ京都
1
自己紹介 • うたがわきき (@utgwkk) • 株式会社はてな ◦ Webアプリケーションエンジニア • 好きなパッケージはreflect
2
アジェンダ • golangci-lintについて • lintルールを強くするためにまずやったこと • あとからlintルールを強くするコツ 3
アジェンダ • golangci-lintについて • lintルールを強くするためにまずやったこと • あとからlintルールを強くするコツ 4
golangci-lintについて • https://golangci-lint.run/ • Goのlinterをまとめて実行するrunner • アンケート: golangci-lintを使っている? 5
アジェンダ • golangci-lintについて • lintルールを強くするためにまずやったこと • あとからlintルールを強くするコツ 6
golangci-lintは使っていたが • 最小構成でスタート • 検査しないファイルだけ設定する • デフォルトで有効のlinterのみ • CIで走らせる 7
設定をよくする機運が高まる • 実装ミスがlinterで検知されると嬉しい • どこまで検査してくれるのか知らなかった • 底力を引き出せていないのでは 8
9 よっしゃやっていくぞ
10 まずは何をするか • 全てのlinterを有効にする?
11 全てのlinterを有効にする? • エラーが大量に出てしまう • 既存のコードベースに合わせた調整が困難 • 設定項目が無限にある!!
まずはgolangci-lintを知る (1) • golangci-lint自体の設定項目を知る • どこまで柔軟にできるか・できないか知る • https://golangci-lint.run/usage/configur ation/ 12
まずはgolangci-lintを知る (2) • 搭載されているlinter一覧がある • 上から順番に見ていく • 1つずつ有効にして検査してみる • https://golangci-lint.run/usage/linters/
13
14 golangci-lintを知った • どんなlinterが搭載されているのか知る • 無理なく導入できるlinter・設定が分かる • 既存のコードベースに合わない設定を知る
15 完全に理解した
アジェンダ • golangci-lintについて • lintルールを強くするためにまずやったこと • あとからlintルールを強くするコツ 16
17 あとからlintルールを強くするコツ • linterの象限を考えて導入する • 部分的にlinterを有効化・無効化する
linterの象限 • コーディング規約に合う・合わない • 簡単に導入できる・できない • (他にもあると思うけど簡略化した) 18
コーディング規約に合う • コーディング規約に合う・簡単に導入できる ◦ linterに引っかかるコードがない (多くない) ◦ 機械的に修正できて動作確認が容易である ◦ 設定を少し調整したら有効化できる
• 迷わず有効化する 19
コーディング規約に合う • コーディング規約に合う・簡単に導入できない ◦ 既存のコードが引っかかりまくる ◦ 機械的に修正できるか判断しづらい 20
コーディング規約に合う • 部分的にlinterを有効化できないか検討する ◦ 特定のファイルだけ有効・無効にする ◦ 特定のディレクトリ以下だけ有効・無効にする ◦ 既存のコードに対してlinterを無効化する •
(具体的な実現方法は後述します) 21
コーディング規約に合わない • コーディング規約に合わないlinter • 基本的には導入しなくていいだろう ◦ 簡単には導入できないなら、なおさら ◦ こういうlinterがある、というのを知っておくことは 損にはならない
22
23 部分的にlinterを有効化・無効化する • ファイル単位で切り替える ◦ 例: テストコードかどうかで切り替える • //nolint: ディレクティブを活用する
• 固有のディレクティブを活用する ◦ 例: exhaustruct
24 ファイル単位で切り替える • exclude-files ◦ 指定したファイルは検査しない • exclude-dirs ◦ 指定したディレクトリ以下は検査しない
• exclude-rules ◦ 指定したファイルで有効にするlinterを変える
25 例: テストコードかどうかで切り替える # テストコードでは特定の linterを無効化する例 exclude-rules: - path: _test\.go
linters: - contextcheck - noctx
26 //nolint: を活用する • //nolint: で始まるコメントを書いた行に対す るlintエラーは報告されない ◦ eslint-disable-next-lineみたいなイメージ •
lintエラーを抑制する理由を書ける ◦ //nolint:unused // ここに理由
//nolint: を活用する var x int //nolint:unused // インライン //nolint:unused //
次の行 var y int 27
28 ディレクティブを活用する • linter固有のディレクティブが使える場合があ る ◦ 同じファイル内でも挙動を切り替えられる ◦ 徐々にコードベースを良くする足がかりとなる
29 固有のディレクティブを活用する • 例: exhaustruct ◦ structリテラルの全てのフィールドに値が埋まってい ることを検査するlinter ◦ //exhaustruct:enforce
と書いた次の行だけlinterの 検査対象となる
まとめ • 一気に全部やろうとしない ◦ enable-all, disable-all以外の選択肢もある ◦ 「要はバランス」 • 部分的に有効化できるルールを活用する
◦ 敷いたガードレールに行き手を阻まれないように 30
31 ここから先 時間余ったら・質問があっ たら取り上げるコーナー
トピック集 • linterから見るGoの進化 • 独自linterの運用 (未解決) • 循環的複雑度をlintする? • チームで有効にしているlinter
• ISUCONでもlinterを活用している 32
linterから見るGoの進化 • exportloopref ◦ ループ変数をコピーせずに参照を取るコードを検出する • copyloopvar ◦ ループの先頭でループ変数をコピーするコードを検出する •
linter同士が衝突している? 33
linterから見るGoの進化 • Go 1.22でループ変数がコピーされるように なった ◦ Fixing For Loops in
Go 1.22 • exportlooprefがdeprecatedになった 34
linterから見るGoの進化 • 言語の進化によって正解が変わる • Go 1.23で導入されたiteratorに対する linterもいつかは出てくるでしょう 35
linterから見るGoの進化 • Go 1.22以降のループ変数のコピーについて は以下の資料が詳しい ◦ 詳解 "Fixing For Loops
in Go 1.22" 自作linterを golangci-lintへコントリビュートした話 36
独自linterの運用 (未解決) • 独自linterは意外と簡単に書ける ◦ コツが掴めたらいける ◦ 日本語の情報も割とある ▪ つくってまなぶ静的解析のすすめ
- LayerX エンジニアブロ グ など 37
独自linterの運用 (未解決) • CIにどうやって組み込む? ◦ CIがコケないと無視される (無視してしまう) • golangci-lintにプラグインの仕組みはあるが ◦
カスタムビルドしたバイナリを使う必要がある ◦ linter側でinitでプラグインを登録する必要がある 38
独自linterの運用 (未解決) • go vet -vettoolの仕組みがgolangci-lintでも 使えると楽になりそうだが…… ◦ Goの静的解析ツールを簡単に使うためのエコシステム について考える
#golang - tenntenn.dev 39
独自linterの運用 (未解決) • 既存のlinterで解決できないか検討する ◦ 探すと意外と見つかることもある ◦ 正規表現マッチで事足りるならforbidigoとか • 探したけど見つからない場合
◦ 新規性チャンス 40
独自linterの運用 (未解決) • 作らずに話すのもな、と思って実装した ◦ https://github.com/utgwkk/goqumysqllint ◦ goqu (クエリビルダ) に対するlinter
41
循環的複雑度をlintする? • gocyclo linterで検査できるが • 答えを持ち合わせていない ◦ 最大値をどこに設定すべきか ◦ 「lintエラー」にすべきなのか
42
チームで有効にしているlinter • contextcheck • depguard • exhaustive • exhaustruct •
fatcontext • gocheckcompilerdirec tives • makezero 43 • mirror • misspell • nilerr • noctx • nolintlint • predeclared • reassign • unconvert
contextcheck • context.Contextを引き回しているかどうか検査 するlinter • テストコードでは無効にしている ◦ ヘルパー関数がいっぱいあるから • https://github.com/kkHAIKE/contextcheck
44
exhaustive • enumに対するswitch-caseの分岐が網羅され ているか検査するlinter • https://github.com/nishanths/exhaustive 45
exhaustruct • structの全てのフィールドに値が埋まってい ることを検査するlinter • https://github.com/GaijinEntertainment /go-exhaustruct 46
fatcontext • context.Contextが肥大化するコードを検出 するlinter ◦ 例: forループ内でcontext.Contextを同じ変数に再代 入する • https://github.com/Crocmagnon/fatcon
text 47
gocheckcompilerdirectives • compiler directiveが正しいことを検査する linter ◦ //go: で始まるコメント群のこと • https://github.com/leighmcculloch/goch
eckcompilerdirectives 48
makezero • スライスのlenを指定して初期化したのに appendしているコードを検出するlinter • https://github.com/ashanbrown/makezero 49
misspell • スペルミスを検出するlinter • 同名のツールは有名だと思う ◦ 実はGoのlinterとしても走らせられる • https://github.com/client9/misspell 50
nilerr • 適切にエラーハンドリングできていないコード を検出するlinter ◦ if err != nil の分岐内でエラーを返していない
◦ if err == nil の分岐内でエラーを返している • https://github.com/gostaticanalysis/nilerr 51
noctx • context.Contextを使わずにHTTPリクエス トを送るコードを検出するlinter • https://github.com/sonatard/noctx 52
nolintlint • //nolint コメントが適切に使われていることを 検査するlinter ◦ 抑制するlinterが指定されている、など • https://github.com/ashanbrown/nolintlint 53
predeclared • Goの予約済キーワードと重複する変数名を使っ ていないか検査するlinter ◦ Goの予約済キーワードの一覧 • https://github.com/nishanths/predeclared 54
reassign • package単位のグローバル変数を他のpackageか ら再代入していないか検査するlinter • https://github.com/curioswitch/go-reassign 55
unconvert • 不要な型変換を行うコードを検出するlinter ◦ int型をint型に変換する、など • https://github.com/mdempsky/unconvert 56
チームで有効にしているlinter • いかがでしたか? • デフォルト有効のlinterも有効です 57
ISUCONでもlinterを活用している • 前提: ISUCONについて ◦ >ISUCONとはLINEヤフー株式会社が運営窓口となっ て開催している、お題となるWebサービスを決められ たレギュレーションの中で限界まで高速化を図る チューニングバトルです ◦
https://isucon.net/ 58
ISUCONでもlinterを活用している • 前提: ISUCONについて ◦ つまり? ◦ 8時間でWebサービスを高速にする 59
ISUCONでもlinterを活用している • デフォルト設定でlintされている • 呼んでない関数や使ってない引数が分かる ◦ 実装をスリムにできると有利 ◦ 使ってない実装をじゃんじゃん消せると有利 60