Upgrade to PRO for Only $50/Year—Limited-Time Offer! 🔥

golangci-lintの Module Plugin System をちょっと詳しく

kuro
July 12, 2024

golangci-lintの Module Plugin System をちょっと詳しく

2024/07/12 Go Connect #1のLT資料です。

参考リンク
Module Plugin System | golangci-lint
https://golangci-lint.run/plugins/module-plugins/

PR feat: new custom linters system
https://github.com/golangci/golangci-lint/pull/4437

golangci-lintのModule Plugin Systemが良さそうなので使ってみた
https://zenn.dev/team_soda/articles/47087ee189cfd7

plugin - Go Packages
https://pkg.go.dev/plugin

plugin-module-register
https://github.com/golangci/example-plugin-module-linter/tree/main

The Go Programming Language Specificationspec#Import_declarations
https://go.dev/ref/spec#Import_declarations

init関数のふしぎ #golang #Go - Qiita
https://qiita.com/tenntenn/items/7c70e3451ac783999b4f

kuro

July 12, 2024
Tweet

More Decks by kuro

Other Decks in Programming

Transcript

  1. Plugin Systemにも2つの方法がある 1. Go Plugin System 2. Module Plugin System

    →両方共通するのは、golangci-lint自体と自分で作った linterを何らかの形でまとめて、buildして動かそうという部 分。 特にbuildの方法に違いがある。
  2. 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後に異なる環境ではうまく動かないことがある。 →割と辛みがある。。。
  3. 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
  4. 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 ⑧バイナリが指定された場所に移動される。
  5. 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" )
  6. 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 で、自身を登録している。
  7. 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)
  8. 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とし て使用できる。
  9. 参考 - 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