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
1
200
ゆるやかに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.4k
Goでリフレクションする、その前に / Kansai.go #1
utgwkk
5
2k
Go製Webアプリケーションのエラーとの向き合い方大全、あるいはやっぱりスタックトレース欲しいやん / Kyoto.go #50
utgwkk
7
3.3k
ありがとう、create-react-app
utgwkk
4
10k
mockgenによるモック生成を高速化するツール bulkmockgenのご紹介 / Kyoto.go #43
utgwkk
2
2.2k
SPAでもデータをURLでシェアしたい / Kyoto.js 19
utgwkk
2
1.8k
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
採用事例の少ないSvelteを選んだ理由と それを正解にするためにやっていること
oekazuma
2
880
SymfonyCon Vienna 2025: Twig, still relevant in 2025?
fabpot
3
1.1k
競技プログラミングで 基礎体力を身につけよう / You can get basic skills through competitive programming
mdstoy
0
170
複雑な仕様に立ち向かうアーキテクチャ
myohei
0
150
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
290
Chrome DevTools: State of the Union 2024 - Debugging React & Beyond
addyosmani
1
150
tidymodelsによるtidyな生存時間解析 / Japan.R2024
dropout009
1
650
The Efficiency Paradox and How to Save Yourself and the World
hollycummins
1
370
似たもの同士のPerlとPHP
uzulla
1
120
CSC509 Lecture 14
javiergs
PRO
0
130
Criando Commits Incríveis no Git
marcelgsantos
2
160
StarlingMonkeyを触ってみた話 - 2024冬
syumai
3
240
Featured
See All Featured
It's Worth the Effort
3n
183
27k
Building a Scalable Design System with Sketch
lauravandoore
459
33k
Fantastic passwords and where to find them - at NoRuKo
philnash
50
2.9k
Measuring & Analyzing Core Web Vitals
bluesmoon
4
160
How to Think Like a Performance Engineer
csswizardry
21
1.2k
Visualization
eitanlees
145
15k
CSS Pre-Processors: Stylus, Less & Sass
bermonpainter
356
29k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
27
900
Statistics for Hackers
jakevdp
796
220k
個人開発の失敗を避けるイケてる考え方 / tips for indie hackers
panda_program
95
17k
Automating Front-end Workflow
addyosmani
1366
200k
Bootstrapping a Software Product
garrettdimon
PRO
305
110k
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