Slide 1

Slide 1 text

golangci-lintの Module Plugin System をちょっと詳しく 2024/07/12 Go Connect #1 kuroda naoki

Slide 2

Slide 2 text

自己紹介 - 名前:kuroda naoki - 所属:株式会社サイバーエージェ ントAI事業本部 プリズムパートナーカンパニー kuro @knkurokuro7

Slide 3

Slide 3 text

自分で作った linterを golangci-lintの仕組みに のせて実行したくないです か?

Slide 4

Slide 4 text

そもそも自分のlinterをgolangci-lintで動かすには? 1. 本体にPRを送って組み込んでも らう。 2. Plugin Systemを使う。

Slide 5

Slide 5 text

Plugin Systemにも2つの方法がある 1. Go Plugin System 2. Module Plugin System →両方共通するのは、golangci-lint自体と自分で作った linterを何らかの形でまとめて、buildして動かそうという部 分。 特にbuildの方法に違いがある。

Slide 6

Slide 6 text

1. Go Plugin System - Go標準のPluginパッケージ(https://pkg.go.dev/plugin)を内 部で使う。 - CGO_ENABLED=1を指定してbuildする必要がある。 - buildする際に、golangci-lint本体と、Goのバージョンや依存するパッ ケージのバージョンを揃える必要がある。 - 使えるOSに制限がある。(Linux, FreeBSD, and macOS) - build後に異なる環境ではうまく動かないことがある。 →割と辛みがある。。。

Slide 7

Slide 7 text

1. Go Plugin System(Pluginパッケージ) 見るからに辛そ う🥺 引 用)https://pkg.go .dev/plugin#hdr- Warnings

Slide 8

Slide 8 text

2. Module Plugin System - golangci-lint custom コマンドでbuildする。 - go.modファイルを置いて、独自linterをmoduleとする。 - そのmoduleをgolangci-lint本体にblank importする。 - init()関数でレジスタに独自linterが自身を登録しておく。 →golangci-lintがそれをロードして使用する。 →moduleにすることでgolangci-lint自体の依存パッケージになるの で、バージョン等を気にせず使える! 参照:https://github.com/golangci/golangci-lint/pull/4437

Slide 9

Slide 9 text

Module Plugin Systemの流れをもっと詳しく $ golangci-lint custom -v INFO Cloning golangci-lint repository ①goolang-ci lintをcloneしてくる。 INFO Adding plugin imports ②plugins.goファイルが更新され、独自 linterのブランクインポートが追加され る。 INFO generated imports info ③更新されたplugins.goファイルの内容が表示される。 /var/folders/b_/njdcc05n3l39pl3blddtwp99d_p5nj/T/custom-gcl3087053477/golangci-lint/cmd/golangci-l int/plugins.go: package main import ( _ "github.com/hoge/golangci-lint/linter/unnamederr" ) INFO Adding replace directives ④go.modファイルに replace ディレクティブが追加される。 INFO run: go mod edit -replace ⑤パスがローカルのパスに置き換えられる。 github.com/hoge/golangci-lint/linter/unnamederr=/Users/fuga/golangci-lint/linter/unnamederr INFO Running go mod tidy ⑥go mod tidyが実行される。 INFO Building golangci-lint binary ⑦golangci-lintバイナリがbuildされる。 INFO Moving golangci-lint binary ⑧バイナリが指定された場所に移動される。

Slide 10

Slide 10 text

Module Plugin Systemの流れをもっと詳しく package main // This file is used to declare module plugins. https://github.com/golangci/golangci-lint/blob/master/cmd/golangci-lint/plugins.go →②「plugins.goファイルが更新」の部分で以下のようになる。 package main import ( _ "github.com/hoge/golangci-lint/linter/unnamederr" )

Slide 11

Slide 11 text

Module Plugin Systemの流れをもっと詳しく golangci-lint customでbuildされたバイナリをgolangci-lint runで実行する時、 独自linter側に実装された、 func init() { register.Plugin("example", New) } https://github.com/golangci/example-plugin-module-linter/blob/main/example. go で、自身を登録している。

Slide 12

Slide 12 text

blank import To import a package solely for its side-effects (initialization), use the blank identifier as explicit package name https://go.dev/ref/spec#Import_declarations →init関数を実行するだけの用途に使いたいときにblank importす る。 →importするだけでinit関数が実行される。 (依存するパッケージのinit→自身のinit)

Slide 13

Slide 13 text

blank import package main import ( _ "github.com/hoge/golangci-lint/linter/unnamederr" ) →golangci-lint側のプログラム実行時に、unnamederr(独自linter)側のinit関数が 実行される。 func init() { register.Plugin("unnamederr", New) } →golangci-lintが実行される(golangci-lint run)ときに、unnamederrをmoduleとし て使用できる。

Slide 14

Slide 14 text

参考 - Module Plugin System | golangci-lint - github PR feat: new custom linters system - golangci-lintのModule Plugin Systemが良さそうなので使ってみた - plugin - Go Packages - github plugin-module-register - The Go Programming Language Specificationspec#Import_declarations - init関数のふしぎ #golang #Go - Qiita