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
1.4k
ゆるやかに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
自動で //nolint を挿入する取り組み / Gopher's Gathering
utgwkk
1
340
君たちはどうコードをレビューする (される) か / 大吉祥寺.pm
utgwkk
21
14k
Dive into gomock / Go Conference 2024
utgwkk
14
6.4k
Goでリフレクションする、その前に / Kansai.go #1
utgwkk
5
2.8k
Go製Webアプリケーションのエラーとの向き合い方大全、あるいはやっぱりスタックトレース欲しいやん / Kyoto.go #50
utgwkk
7
4k
ありがとう、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
Other Decks in Programming
See All in Programming
AIプログラミング雑キャッチアップ
yuheinakasaka
20
5.3k
Kotlinの開発でも AIをいい感じに使いたい / Making the Most of AI in Kotlin Development
kohii00
5
2k
Visual StudioのGitHub Copilotでいろいろやってみる
tomokusaba
1
230
Django NinjaによるAPI開発の効率化とリプレースの実践
kashewnuts
1
300
『テスト書いた方が開発が早いじゃん』を解き明かす #phpcon_nagoya
o0h
PRO
9
2.6k
PHPのバージョンアップ時にも役立ったAST
matsuo_atsushi
0
230
Amazon Bedrockマルチエージェントコラボレーションを諦めてLangGraphに入門してみた
akihisaikeda
1
170
The Clean ArchitectureがWebフロントエンドでしっくりこないのは何故か / Why The Clean Architecture does not fit with Web Frontend
twada
PRO
59
19k
Drawing Heighway’s Dragon- Recursive Function Rewrite- From Imperative Style in Pascal 64 To Functional Style in Scala 3
philipschwarz
PRO
0
170
もう少しテストを書きたいんじゃ〜 #phpstudy
o0h
PRO
21
4.4k
Boos Performance and Developer Productivity with Jakarta EE 11
ivargrimstad
0
700
楽しく向き合う例外対応
okutsu
0
750
Featured
See All Featured
Building Applications with DynamoDB
mza
93
6.2k
実際に使うSQLの書き方 徹底解説 / pgcon21j-tutorial
soudai
175
52k
Fashionably flexible responsive web design (full day workshop)
malarkey
406
66k
KATA
mclloyd
29
14k
The MySQL Ecosystem @ GitHub 2015
samlambert
251
12k
Cheating the UX When There Is Nothing More to Optimize - PixelPioneers
stephaniewalter
280
13k
Making Projects Easy
brettharned
116
6k
The Web Performance Landscape in 2024 [PerfNow 2024]
tammyeverts
4
440
Performance Is Good for Brains [We Love Speed 2024]
tammyeverts
7
660
Intergalactic Javascript Robots from Outer Space
tanoku
270
27k
Sharpening the Axe: The Primacy of Toolmaking
bcantrill
40
2k
Automating Front-end Workflow
addyosmani
1369
200k
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