golangci-lintとは?
Goのlintツールです。
lintツールはlinterとしても呼ばれ、プログラムのソースコードの静的解析を行い、潜在的なバグを引き起こしそうなコードの発見やコードの命名等が規則に沿っているかどうかを指摘や修正等を行えます。
golangci-lintを使用するメリット
linterは基本的にコードの品質を高めるために使われます。
golangci-lintは、コードの命名規則だけでなく、バグを引き起こしそうなコード、エラーハンドリングしていないコードなど、設定すれば多くのコードの書き方にかける規則の指摘をしてくれます。
加えて、オプションを使えば修正も行なってくれるので、コードレビューをある程度自動化することができます。
インストール
homebrewでは次のコマンドでインストールします。
brew install golangci-lint
GOPATHでは下のコマンドでインストールします。
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0
lintを走らせる
下のコマンドで走らせることができます。
golangci-lint run
もし走らせて、構文エラーがあった場合、下のようにerrを返していないところなどを教えてくれます。
❯ golangci-lint run
usecases/interactor/todo.go:74:16: Error return value of `uc.txm.RunInTx` is not checked (errcheck)
uc.txm.RunInTx(ctx, func(ctx context.Context) error {
^
infrastructure/mysql/conn.go:69:15: ineffectual assignment to err (ineffassign)
sqlDB, mock, err := sqlmock.New()
^
infrastructure/mysql/repository/todo_test.go:56:13: ineffectual assignment to err (ineffassign)
deadline2, err := time.Parse("2006-01-02", "2024-10-12")
^
usecases/interactor/todo.go:75:11: ineffectual assignment to err (ineffassign)
exsist, err := uc.repo.FindById(ctx, strconv.Itoa(int(task.ID)))
^
設定ファイルを書く
設定ファイルを書くことで細かくlintの設定を行うことができます。
設定するために.golangci.yml
を作成して、下のように記述します。
run:
deadline: 5m
allow-parallel-runners: true
linters:
disable-all: true
enable:
- gofmt
- goimports
- govet
- typecheck
- errcheck
- errname
- errorlint
- nilerr
- makezero
- ineffassign
- gosec
- noctx
- staticcheck
- unused
- copyloopvar
- decorder
- misspell
- whitespace
issues:
exclude-dirs:
- config
configで設定した内容
run
linterの実行に関する設定を行なっています。
deadline
でタイムアウトを5分と設定
allow-parallel-runners
で並行処理を許可しています。
run:
deadline: 5m
allow-parallel-runners: true
linters
lintする対象を設定しています。
disable-all
をtrueとすることで実行内容をオプションとしています。
enable
の下にリストとして、何を対象としてlintを行うかを設定しています。
名前 | 効果 |
---|---|
gofmt | go標準のフォーマット |
goimports | インポートしているモジュールの整理 |
govet | go標準の静的解析 |
typecheck | 型定義のチェック |
errcheck | エラーチェック |
errname | エラー変数の命名チェック |
nilerr | エラー確認でnilを返していないかを確認 |
makezero | 長さが0でないスライスに対するappendを確認 |
ineffassign | 不要な代入をされているところを警告します |
gosec | さまざまなセキュリティの確認をします |
noctx | contextなしでhttpリクエストを返してるところを確認します |
staticcheck | 静的解析ツールで確認します |
unused | 使用してないフィールドを検知 |
copyloopvar | ループ変数に関する警告 |
decorder | 構造体や関数などの宣言確認 |
misspell | スペルミスを確認 |
whitespace | 余分な改行を確認 |
linters:
disable-all: true
enable:
- gofmt
- goimports
- govet
- typecheck
- errcheck
- errname
- nilerr
- makezero
- ineffassign
- gosec
- noctx
- staticcheck
- unused
- copyloopvar
- decorder
- misspell
- whitespace
以下でオプションを確認できます。
actionsでgolint-ciを使用する
GithubActionsを使って、lintを適応させてみようと思います。
また、lintの結果をレビューコメントとして出してくれるreviewdogを使おうと思います。
ymlを書いてみる
実際に下のようにymlを記述しました。
name: golangci-lint
on:
push:
branches:
- develop
pull_request:
types:
- opened
- reopened
- synchronize
branches:
- develop
jobs:
lint:
name: lint
permissions:
checks: write
contents: read
pull-requests: write
runs-on: ubuntu-latest
steps:
- name: checkout
uses: actions/checkout@v4.2.2
- name: setup for go
uses: actions/setup-go@v5.1.0
with:
go-version-file: "./server/go.mod"
- name: lint
uses: reviewdog/action-golangci-lint@v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
workdir: "./server"
go_version_file: "./server/go.mod"
level: error
fail_on_error: true
golangci_lint_flags: "--config=./config/.golangci.yml"
filter_mode: nofilter
develop
ブランチを作成、もしくはPullRequestをdevelopに対して作成
、draftを作成
、PRに新しいコミット
を増やした時にActionsを行うようにします。
on:
push:
branches:
- develop
pull_request:
types:
- opened
- reopened
- synchronize
branches:
- develop
jobs配下に権限(permission)や実行OS(runs-on)を設定します。
permissionでは、GithubTokenに対する権限を付与しています。今回、lintのciを回すためにcontents: read
、reviewdogによるPRにコメントを残すためにchecks: write
とpull-requests: write
を設定しています。
jobs:
lint:
name: lint
permissions:
checks: write
contents: read
pull-requests: write
runs-on: ubuntu-latest
stepsに各々行う処理を記述しています。
steps:
- name: checkout
uses: actions/checkout@v4.2.2
- name: setup for go
uses: actions/setup-go@v5.1.0
with:
go-version-file: "./server/go.mod"
- name: lint
uses: reviewdog/action-golangci-lint@v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
workdir: "./server"
go_version_file: "./server/go.mod"
level: error
fail_on_error: true
golangci_lint_flags: "--config=./config/.golangci.yml"
filter_mode: nofilter
checkout
でactions内にリポジトリをクローンします。
- name: checkout
uses: actions/checkout@v4.2.2
actionsにgoの環境をセットアップします。
- name: setup for go
uses: actions/setup-go@v5.1.0
with:
go-version-file: "./server/go.mod"
lintを実行します。
reviewdogにgolangci-lint向けのactionsが用意されているのでそれを使用します。
- name: lint
uses: reviewdog/action-golangci-lint@v2
with:
github_token: ${{ secrets.GITHUB_TOKEN }}
reporter: github-pr-review
workdir: "./server"
go_version_file: "./server/go.mod"
level: error
fail_on_error: true
golangci_lint_flags: "--config=./config/.golangci.yml"
filter_mode: nofilter
level
をerrorにすることで、lintで発見した内容をerrorとすることができ、fail_on_error: true
でactionsを停止させることができます。
また、filter_mode: nofilter
で変更したコード以外もチェックしてくれます。
今回使用したプロパティはこんな感じです。
プロパティ | 役割 |
---|---|
github_token | GithubのAPIを叩くためのトークンを指定 |
reporter | golangci-lintの実行結果をどう示すか |
workdir | 作業ディレクトリの指定 |
go_version_file | go.modのある場所を指定 |
level | 実行結果をどの程度のレベルで表示するかを指定 |
fail_on_error | errorが出ても処理を続けるように |
golangci_lint_flags | golangci-lintを動かす際のオプション等の引数を付け足す |
filter_mode | lintを回すコードのスコープ(added,file,nofileter) |
実行してみる
実際にactionsを走らせるとFiles Changed
等で下のように表示してくれます。
golangci-lintを使うことでコードの品質を上げ、共同開発の効率を上げてくれます。
ぜひ活用してみてください!