Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Sign up for free
Menu
Search
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Features
All features
Private URLs
Password Protection
Custom URLS
Scheduled publishing
Remove Branding
Restrict embedding
Deck Collections
Notes
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Explore
Featured decks
Featured speakers
Programming
Technology
Storyboards
Pricing
Search
Sign in
Sign up for free
golangci-lint の enable-all で コーディングルールを明確にする試み
Search
Sponsored
·
Ship Features Fearlessly
Turn features on and off without deploys. Used by thousands of Ruby developers.
→
takanakahiko
May 10, 2024
Technology
83
0
Share
Embed
Copy iframe code
Copy JS code
Copy link
Start on current slide
golangci-lint の enable-all で コーディングルールを明確にする試み
takanakahiko
May 10, 2024
More Decks by takanakahiko
See All by takanakahiko
Vivliostyle Pub の現状と課題 #vivliostyle / Current status and issues of Vivliostyle Pub
takanakahiko
0
1.8k
思いつきで実装した web-demo-suit が そこそこバズってメディアとかにも取り上げられた.pdf
takanakahiko
1
220
オタクLODをやりませんか #uzimaru生誕LT会
takanakahiko
0
150
かしこま! 女児向けアニメのLODをみんなで作ってる話
takanakahiko
0
340
学生だけど OSS 始めちゃいました
takanakahiko
3
2.7k
GAS活 #4 「Claspを用いた モダンGAS開発」
takanakahiko
2
1.8k
学生が OSS に挑戦すること
takanakahiko
0
3.2k
プリパラで学ぶ プログラミング(&表現の極意)
takanakahiko
0
1.9k
gas-kastu-2
takanakahiko
1
1.5k
Other Decks in Technology
See All in Technology
小規模OSSモデルは サイバーセキュリティ業務に どこまで使えるか
bbrbbq
0
300
なぜAI時代に技術記事を書くのか?どう書くのか? 〜bunの場合〜
kworkdev
PRO
0
130
「作れる」と「リリースできる」の間にあったもの── PdMを外して見えた、PdMがやるべき仕事/Buildable ≠ Shippable: What Removing the PM Taught Me About the PM’s Job
yappli_developers
0
280
ドメインエキスパートは いかにして AI を使って プロダクト開発をするか
tatsuyashiraishi
1
190
Claude for Google Workspaces ポン出し/claude-for-google-workspace-slide-conversion
emiki
0
13k
Devin プロモコードの受け取りと適用(2026.10.27)
kinopeee
0
500
顧客価値を追いかけたら、プライシングにたどり着いた
sansantech
PRO
2
1k
スクラム祭り2026福井トラック_閉じたループから価値のスパイラルへ
kc_nakanishi
0
170
FinOps Agentが生んだ技術負債:コスト自動調査の落とし穴と解消までの道のり
oasis1994liveforever
3
300
【データ横丁主催】AI エージェント時代のTranslytical Data Platform
shisyu_gaku
0
300
DevelopersIO2026 -バックアップは“消されないこと”が9割-
yoshida0129
0
410
LLM Content Moderationを支える評価・改善ループの実践
suikabar
2
360
Featured
See All Featured
Conquering PDFs: document understanding beyond plain text
inesmontani
PRO
4
3.2k
GitHub's CSS Performance
jonrohan
1033
470k
Navigating Team Friction
lara
192
16k
Digital Ethics as a Driver of Design Innovation
axbom
PRO
1
460
職位にかかわらず全員がリーダーシップを発揮するチーム作り / Building a team where everyone can demonstrate leadership regardless of position
madoxten
70
67k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
38
3.1k
Leadership Guide Workshop - DevTernity 2021
reverentgeek
1
410
Breaking role norms: Why Content Design is so much more than writing copy - Taylor Woolridge
uxyall
1
460
Bootstrapping a Software Product
garrettdimon
PRO
306
120k
Save Time (by Creating Custom Rails Generators)
garrettdimon
PRO
33
5.4k
How to make the Groovebox
asonas
2
2.5k
Let's Do A Bunch of Simple Stuff to Make Websites Faster
chriscoyier
508
140k
Transcript
golangci-lint の enable-all で コーディングルールを明確にする試み なかひこくん(@takanakahiko) @Asakusa.go #2
誰? @takanakahiko なかひこくん 新横浜(実は浅草の飛び地なんです!)に住んでいます
さっそく 皆さんに質問 type Runer interface { Run() } type Human
struct { name string } func (h *Human) Run() { ... } // 上記の Human が Runer を実装していることを確認する // 皆さんはどっちで書きますか? var _ Runer = &Human{} // ① var _ Runer = (*Human)(nil) // ② Human が Runer を実装して いることを確認したいです。 皆さんならどっちの書き方にし ますか?
- どっちでも問題はない(メリットやデメリットはあるが)と思う - ただしどちらかに統一されていると必要はある(これが大事) こういうのとても多いですよね。 補足: go.dev/doc ではポインタなら②が例示はされている https://go.dev/doc/faq#guarantee_satisfies_interface 自分としては
チームではこういうのを決めて統一する必要がある - 結局どちらに統一するのか? - これを決めるための何かしらの方針が欲しい - なぜそちらの書き方で書くのか? - この理由を明確にしておきたい(とりあえず?明確に必然性があるから?) -
どう徹底(統一)する? - レビュワーが指摘する?でもそれって仕組み化したいよね なんだかんだこういうのが大変なんですよね チームで書くときは?
- go向けのlinter詰め合わせセット - サードパーティで開発されたやつを取り込んでいる形 - 利用者側は .golangci.yml で利用する linter を選択する
- 君だけの最強の .golangci.yml で勝利を勝ち取れ! こういう時に役立つのが golangci-lint
こんな感じで叱ってくれる。 色々なlinterから叱られてるのがわかると思う。
(再掲) 皆さんに質問 type Runer interface { Run() } type Human
struct { name string } func (h *Human) Run() { ... } // 上記の Human が Runer を実装していることを確認する // 皆さんはどっちで書きますか? var _ Runer = &Human{} // ① var _ Runer = (*Human)(nil) // ② Human が Runer を実装して いることを確認したいです。 皆さんならどっちの書き方にし ますか?
そこで golangci-lint enable-all を使ってみる。 すると何やら怒られる。 # .golangci.yml linters: # enable-all
で全てのlinterを有効化 enable-all: true
main.Human is missing field name (exhaustruct) → なるほど!① var _
Runer = &Human{} だとstruct fieldの設定漏れを許 容するようなソースコードになるから指摘されるんだね → struct fieldの設定漏れは検知できる仕組みが欲しいし、それに変な 例外は作りたくなので② var _ Runer = (*Human)(nil) に統一しよう こうやって対応を決めることができる
- やらないことを決める方が負荷が少ない - やらないことの理由を挙げる方が明確にしやすい - linterを逐次設定する方針だと「採用しない理由」がわかりづらい - disable-all かつ enable
で逐次指定する形 - 「イケているlinterが採用されていない!」→「考慮漏れ?」「後回しになっているだ け?」「理由があって対応していない?」と分かりづらい なぜ enable-all ?
この運用をするときの .golangci-lint.yml の例 # https://github.com/takanakahiko/discord-tts/blob/2195764ba46d1d6b251cea4f29b0cd9e6839d824/.golangci.yml linters: enable-all: true disable: -
wsl # 余計な改行をなるべく含まないようにすることで得られる見通しの良さを重視するため - nlreturn # 上記と同様 - gosmopolitan # 現在はi18n/l10nを検討していないため - depguard # 規模的に依存関係の流れを厳格に管理する必要性はないため - forbidigo # いまのところ特に禁止したい表現はないため - gomnd # The linter 'gomnd' is deprecated - execinquery # The linter 'execinquery' is deprecated # 続く (大袈裟だが) 理由をつけてdisableをする
この運用をするときの .golangci-lint.yml の例(2) # 続き linters-settings: varnamelen: ignore-decls: - v
*discordgo.VoiceStateUpdate # パッケージの使用例がその命名であるため - m *discordgo.MessageCreate # パッケージの使用例がその命名であるため revive: rules: - name: unexported-return disabled: true # ireturnへの対応を優先するため # 続く linterの個別設定の カスタマイズにも理由があると嬉しい
この運用をするときの .golangci-lint.yml の例(3) # 続き linters-settings: funlen: lines: 100 #
デフォルトの60だと余計な関数の分割が発生するため statements: 60 # デフォルトの40だと余計な関数の分割が発生するため gomoddirectives: replace-allow-list: - github.com/jonas747/dca # 該当パッケージが壊れているので独自にパッチを当てたものを利用したいため cyclop: max-complexity: 24 # デフォルトの10だと余計な関数の分割が発生するため 現状このリポジトリの最大値は 23なので24を設定。(この場合は「23になるのは仕方がないよね」という共通認識を作れているはず ) こう設定することで、 complexityの最大値を更新するような次の変更があったらそのタイミングで議論の機会が生まれる。
- .golangci.yml の編集のハードルは極力下げるように努力すべき - 必要以上にコーディングに制約を作ることが目的ではない - 「いまこうなっている理由」を明確にしているだけ - 「いまこうなっている理由」より優先すべきものがあったらガンガン変更する -
「今考えたものが最高で絶対的なルール」なんてあり得ない → 後から入る人がその人 たちにとって心地よいルールにしてくれるという信頼をチームで醸成する - disabeの理由として「あとで対応する」もガンガン許容する - 「あとで対応する」ことが分かっているなら目的は達成できている - 「なぜ対応されていないのか分からない」が一番避けるべき状態 注意点
- golangci-lint のアップデート時にlinterが増えるのでメンテが大変 - だが、その時に方針をチームメンバーで話し合えるのは良いことだと思う - 言語のバージョンをあげてから暫くして上げるのがおすすめ (linterが対応する期間 を待つ) -
明らかに不要なlinterにも理由をつけてdisableする必要がある - でも「明らかに」って自分の感想でしかないので、やっぱり明文化は必要だと自分は 思います - 言語化することでジュニアに「当たり前」の感覚を共有するのも大事 デメリット(と感じられそうなもの)
- golangci-lint で enable-all をすると表記のブレが減らせる - 取り上げていないlinterを理由付きで無効化することができる - 「対応していない理由」が明確になる! -
(アップデート時の .golanci.yml のメンテナンスが少し大変) - みんなどうやってるかハッシュタグとかで教えて欲しい〜 まとめ