golangci-lint

Table of Contents

  1. 解決する問題
  2. インストール
  3. 基本コマンド
  4. v2 の主な変更点
  5. 設定ファイル (.golangci.yml)
    1. default オプション
  6. 主要な Linter
    1. バグ検出
    2. コード品質
    3. フォーマッター(v2 で分離)
  7. CLI オプション
  8. IDE 連携
    1. VS Code
  9. 注意点
  10. 参考リンク
  11. やりたいこと別 Linter ガイド
    1. エラー処理を改善したい
    2. バグを早期発見したい
    3. パフォーマンスを改善したい
    4. セキュリティを強化したい
    5. HTTP・ネットワーク周りの問題を防ぎたい
    6. SQL・データベースの問題を防ぎたい
    7. 分散トレーシングの問題を防ぎたい
    8. コードの複雑度を抑えたい
    9. テストの品質を上げたい
    10. コードスタイル・命名を統一したい
    11. コードの重複を減らしたい
    12. 構造体・型の設計を改善したい
    13. コードのモダナイズ・ベストプラクティス
  12. Linter 別の解説

golangci-lint は Go 向けの高速な Linter アグリゲーターです。100 以上の Linter を並列実行し、キャッシュを活用して高速に解析します。

解決する問題

Go には go vetstaticcheck など優れた Linter が多数存在しますが、個別に実行・管理するのは手間がかかります。

1
2
3
4
5
6
# 個別に実行すると面倒
go vet ./...
staticcheck ./...
errcheck ./...
gosec ./...
# ... まだまだある

golangci-lint はこれらを一括管理し、並列実行・キャッシュ・統一設定で効率的に解析できます。

1
2
# これだけで全 Linter を実行
golangci-lint run

インストール

1
2
3
4
5
6
7
8
# Go install(推奨)
go install github.com/golangci/golangci-lint/v2/cmd/golangci-lint@latest

# Homebrew
brew install golangci-lint

# バージョン確認
golangci-lint version

基本コマンド

コマンド 用途
golangci-lint run Linter を実行
golangci-lint run ./... サブパッケージも含めて実行
golangci-lint fmt フォーマッターを実行(v2 で追加)
golangci-lint help linters 利用可能な Linter の一覧を表示
golangci-lint migrate v1 設定を v2 形式に変換

v2 の主な変更点

golangci-lint v2 では設定構造が大きく変わりました。

v1 v2
linters.enable-all: true linters.default: all
linters.disable-all: true linters.default: none
--enable-all --default=all
--disable-all --default=none
linters-settings: linters.settings: + formatters.settings:

v2 ではデフォルトの除外ルールが廃止され、代わりに人間が読みやすいプリセットが導入されました。

プリセット 用途
comments コメント関連の誤検知を除外
std-error-handling 標準ライブラリのエラー処理に関する警告を除外
common-false-positives よくある誤検知を除外
legacy v1 互換の除外ルール

設定ファイル (.golangci.yml)

プロジェクトルートに .golangci.yml を配置します。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
version: "2"

linters:
default: standard
enable:
- errcheck
- govet
- staticcheck
- unused
- gosimple
- ineffassign
- typecheck
- gocritic
- gosec
- prealloc
- bodyclose
- noctx
- exhaustive

formatters:
enable:
- gofmt
- goimports

issues:
exclude-rules:
- path: _test\.go
linters:
- gosec
- prealloc

run:
timeout: 5m

default オプション

linters.default で基準となる Linter セットを選択できます。

説明
none すべて無効。enable で個別に有効化
fast 高速な Linter のみ有効
standard 標準的な Linter セット(デフォルト)
all すべての Linter を有効化

主要な Linter

バグ検出

Linter 検出内容
govet go vet と同等。構造体タグ、printf フォーマットなど
staticcheck 広範な静的解析。到達不能コード、非推奨 API の使用など
errcheck 未チェックのエラー戻り値
bodyclose HTTP レスポンスボディの閉じ忘れ
noctx context なしの HTTP リクエスト
gosec セキュリティ問題(SQL インジェクション、ハードコードされた認証情報など)

コード品質

Linter 検出内容
unused 未使用の変数、関数、型
ineffassign 効果のない代入
gocritic コードスタイル、パフォーマンス、バグの可能性
gosimple 簡略化可能なコード
prealloc 事前割り当て可能なスライス
exhaustive switch 文の網羅性チェック

フォーマッター(v2 で分離)

フォーマッター 用途
gofmt 標準フォーマッター
goimports import 文の整理
gofumpt gofmt の厳格版
gci import 文のグループ化と並び替え

CLI オプション

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 特定の Linter だけ実行
golangci-lint run --default=none -E errcheck -E govet

# 特定の Linter を無効化
golangci-lint run -D errcheck

# 高速 Linter のみ
golangci-lint run --fast-only

# 新しい問題のみ(CI での差分チェック向き)
golangci-lint run --new

# 特定のパスを指定
golangci-lint run ./internal/...

IDE 連携

golangci-lint は主要な IDE・エディタと連携できます。

VS Code

1
2
3
4
{
"go.lintTool": "golangci-lint",
"go.lintFlags": ["--fast"]
}

go_metalinter_command = ‘golangci-lint’

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18

## GitHub Actions

```yaml
name: Lint
on: [push, pull_request]

jobs:
lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v6
- uses: actions/setup-go@v5
with:
go-version: stable
- uses: golangci/golangci-lint-action@v6
with:
version: latest

注意点

  • Go バージョン対応 - Go チームと同じく最新 2 つのマイナーバージョンをサポート
  • キャッシュ - Go のビルドキャッシュと解析結果キャッシュを活用するため、2 回目以降は高速
  • v1 からの移行 - golangci-lint migrate で設定ファイルを自動変換できる
  • false positive - 誤検知がある場合は //nolint:lintername でインラインで抑制できる(理由を //nolint:lintername // reason で付けるのが推奨)

参考リンク

やりたいこと別 Linter ガイド

エラー処理を改善したい

Linter できること
errorlint errors.Is / errors.As を使った正しいエラー比較を強制
wrapcheck 外部パッケージのエラーにコンテキストをラップしているか検出
errname エラー変数の Err プレフィックス、エラー型の Error サフィックスを強制
nilerr エラーをチェックしたのに nil を返してしまうパターンを検出
nilnil nil, nil を返すパターン(エラーの握りつぶし)を検出

バグを早期発見したい

Linter できること
staticcheck 到達不能コード、非推奨 API、不正な関数呼び出しなど広範な静的解析
gocritic 100 以上のチェックでバグの可能性、スタイル、パフォーマンスを診断
exhaustive switch 文で enum の全ケースが網羅されているかチェック
forcetypeassert ok チェックなしの危険な型アサーションを検出
asasalint 可変長引数の展開忘れ(argsargs...)を検出
durationcheck time.Duration 同士の掛け算(よくあるバグ)を検出
reassign パッケージレベル変数(センチネルエラーなど)の再代入を防止

パフォーマンスを改善したい

Linter できること
prealloc ループ内でスライスの事前割り当てが可能な箇所を提案
perfsprint fmt.Sprintf をより高速な strconv 系関数に置き換え
unconvert 不要な型変換を検出して削除
mirror []byte / string 間の不要な変換を直接関数に置き換え
makezero make で非ゼロ長のスライスを作った直後の append を検出

セキュリティを強化したい

Linter できること
gosec SQL インジェクション、ハードコード認証情報、弱い暗号など
noctx context.Context なしの HTTP リクエストを検出

HTTP・ネットワーク周りの問題を防ぎたい

Linter できること
bodyclose HTTP レスポンスボディの閉じ忘れを検出
canonicalheader HTTP ヘッダー名の正規形式(Content-Type など)を強制
noctx context.Context を渡さない HTTP リクエストを検出

SQL・データベースの問題を防ぎたい

Linter できること
rowserrcheck クエリ結果のイテレーション後に rows.Err() をチェックしているか検出
sqlclosecheck sql.Rowssql.Stmt の閉じ忘れを検出

分散トレーシングの問題を防ぎたい

Linter できること
spancheck OpenTelemetry スパンの End() 呼び忘れやエラー記録漏れを検出

コードの複雑度を抑えたい

Linter できること
gocognit 認知的複雑度(ネストの深さを考慮した読みやすさ指標)をチェック
gocyclo 循環的複雑度(分岐数ベースの複雑さ指標)をチェック
nestif 深くネストされた if 文を検出

テストの品質を上げたい

Linter できること
paralleltest テスト関数で t.Parallel() の呼び出しを強制
thelper テストヘルパー関数の先頭で t.Helper() を呼んでいるかチェック
testifylint testify のアサーション関数の正しい使い方をチェック
testpackage テストファイルが外部テストパッケージ(_test サフィックス)を使用しているかチェック
tenv テスト内の os.Setenvt.Setenv に置き換えるよう提案

コードスタイル・命名を統一したい

Linter できること
revive 100 以上のルールで命名規則、コードスタイル、ドキュメントをチェック
tagliatelle 構造体タグの命名規則(camelCase / snake_case)を統一
importas import エイリアスの一貫性を強制
decorder 宣言順序(type → const → var → func)を強制
misspell コードやコメント内のスペルミスを検出
dupword コードやコメント内の重複単語を検出
whitespace ブロック先頭・末尾の不要な空行を削除
wsl_v5 論理ブロック間の適切な空行を強制

コードの重複を減らしたい

Linter できること
dupl コピー&ペーストで生まれた重複コードを検出
goconst 繰り返し使われるリテラル文字列・数値を定数化するよう提案

構造体・型の設計を改善したい

Linter できること
exhaustruct 構造体の全フィールドが初期化されているか検証
containedctx 構造体フィールドへの context.Context の格納を禁止
fatcontext ループ内でのコンテキスト肥大化(メモリリークの原因)を検出
musttag Marshal / Unmarshal に渡す構造体にタグが付いているかチェック

コードのモダナイズ・ベストプラクティス

Linter できること
usestdlibvars 文字列リテラルを標準ライブラリの定数(http.MethodGet 等)に置き換え
exptostd golang.org/x/exp を標準ライブラリの同等機能に置き換え
forbidigo 禁止関数(fmt.Println などデバッグ用コード)の使用を検出
predeclared 組み込み識別子(errorlen など)のシャドウイングを防止
goheader ソースファイルの著作権・ライセンスヘッダーを強制
gocheckcompilerdirectives Go コンパイラディレクティブの書式を検証
nolintlint //nolint ディレクティブに理由と対象 Linter の明記を強制

Linter 別の解説