【golangci-lint】GoのLinter導入(CI含む)

# 【概要】

本記事は、golangci-lintを使用したGoのLinterを導入方法の記事となります。

個人や社内のGo開発の効率化にご利用ください。


# 【0.そもそもリンターとは】
リンターとはプログラムの「間違い」や「良くない書き方」を教えてくれるツールです。

類似のツールとしてフォーマッターがありますが、フォーマッターはコードの書式を自動的に整えるツールで、リンターは潜在的なエラーや、コーディング規約に反する箇所を指摘してくれるツールです。


# 【1.本記事の最終系】

本記事は最終的に以下のようなリンターをGo環境に導入できます。

- golangci-lintによるリンター
- Github Actionsを使用したCI(自動のリンター)
- Reviewdogを使用し、リント結果をプルリクのコメントとして出力

「リポジトリへのプッシュ」または「プルリクの作成・更新」時に、自動でリンターがプルリクの差分に対してだけ実行され、レビューコメントとして解析内容を確認できます。設定によっては無視してマージもできるので、肥大化した初期段階のサービスにも導入しやすいものとなっています。

【フォルダ構成】

```html
go-practice/
├── .github/
│   └── workflows/
│       └── golangci-lint.yml
├── .vscode/
│   └── settings.json
├── .golangci.yml
├── go.mod # 内容は省略
├── go.sum # 内容は省略
├── main.go # 内容は省略
```

【golangci-lint.yaml】

```yaml
linters:
  disable-all: true
  enable:
    - bodyclose # HTTPレスポンスのボディが正しく閉じられていない箇所を検出
    - containedctx # 構造体内にcontext.Context型のフィールドが含まれている箇所を検出
    - depguard # インポートしたパッケージが許可リストに含まれていない箇所を検出
    - errcheck # [default]エラーチェックしていない箇所を検出
    - errorlint # エラーラッピング方式に問題をもたらすコード箇所を検出
    - gocritic # バグ、パフォーマンス問題、スタイル違反箇所を検出
    - godox # コメント内の注意喚起キーワード使用箇所を検出
    - gofmt # gofmtに沿わないコード整形箇所を検出
    - goimports # goimportsフォーマット違反箇所を検出
    - gosec # セキュリティ脆弱性箇所を検出
    - gosimple # [default]複雑な処理や不必要な処理を検出
    - govet # [default]Goの公式リンター フォーマット文字列の不整合、誤った型の使用、意図しない挙動を検出
    - ineffassign # [default]不要な変数への代入、計算のミスを検出
    - misspell # スペルミス箇所を検出
    - nakedret # 不適切なnaked return使用箇所を検出
    - nilerr # nilチェックと矛盾するエラー返却箇所を検出
    - revive # コードスタイルや品質問題箇所を検出
    - rowserrcheck # SQL Rowsのエラーチェック不足箇所を検出
    - sqlclosecheck # データベースオブジェクトの不適切なクローズ箇所を検出
    - staticcheck # [default]バグ、パフォーマンス問題、非効率な処理、冗長な表現など幅広い問題を検出
    - unconvert # 不要な型変換箇所を検出
    - unparam # 未使用の関数パラメータ箇所を検出
    - unused # [default]使用されていない変数や関数を検出

linters-settings:
  depguard:
    rules:
      main:
        deny:
          - pkg: io/ioutil
            desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
  revive:
    rules:
      - name: package-comments  # パッケージ/関数コメント disable
        disabled: true
  godox:
    # 検出対象となるキーワードのリスト
    keywords:
      - "TODO"

issues:
  exclude-use-default: false
  max-issues-per-linter: 0
  max-same-issues: 0

output:
  formats:
    - format: colored-line-number
  print-linter-name: true

run:
  timeout: 5m
  tests: false
  modules-download-mode: readonly
  go: '1.24.1'

severity:
  default-severity: error
```

【.vscode/settings.json】

```json
{
	"go.lintTool": "golangci-lint",
	"go.lintFlags": [
		"--fast"
	]
}
```

【.github/workflows/golangci-lint.yaml】

```yaml
name: golangci-lint
on:
  push:
  pull_request:

permissions:
  checks: write        # リント結果の表示権限
  contents: read       # リポジトリのファイルの読み取り権限
  pull-requests: write # プルリクにコメントする権限

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      # リポジトリからソースコードを取得
      - name: Checkout Repository
        uses: actions/checkout@v4

      # Reviewdogによるgolangci-lintの実行
      - name: Run golangci-lint with Reviewdog
        uses: reviewdog/action-golangci-lint@v2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}     # GithubAPI実行用のトークン設定
          go_version: 1.24.1                            # 解析に使用するGoバージョン設定
          reporter: github-pr-review                    # リント結果をレビューとして出力する設定
          level: warning                                # 検出されたissueのレベルをwarningにする設定
          golangci_lint_flags: "--config=.golangci.yml" # .golangci.ymlの内容でリントを実行させる設定
```

# 【2.golangci-lintとは】

GoのLinterツールでgofmt,goimports,govetなどの100以上のLinterが入っています。

# 【3.インストール】

## 3-1. バイナリ

```bash
# インストール
curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/HEAD/install.sh | sh -s -- -b $(go env GOPATH)/bin v1.64.6

# 適用できているか確認
golangci-lint --version
```

## 3-2. brew

```bash
# インストール
brew install golangci-lint

# 手動の更新が必要なため実行
brew upgrade golangci-lint

# 適用できているか確認
golangci-lint --version
```

## 3-3. asdf

```bash
# プラグインを追加
asdf plugin add golangci-lint https://github.com/hypnoglow/asdf-golangci-lint.git

# インストール可能バージョンを表示
asdf list all golangci-lint

# 任意のバージョンを指定してインストール
asdf install golangci-lint <指定バージョン>

# グローバルか、ローカルで適用
asdf global golangci-lint <指定バージョン>

# 適用できているか確認
golangci-lint --version
```

# 【4.基本操作】

## 4-1. golangci-lintの実行

【対象コード】

```go
// 対象コード
import (
	"fmt"
)

func main() {
	unused := "この変数は使われていません"

	fmt.Println("成功")
}
```

【golangci-lintの実行コマンド】

```bash
golangci-lint run
```

【出力結果】

```bash
main.go:8:2: declared and not used: unused (typecheck)
        unused := "この変数は使われていません"
        ^
```

## 4-2. 指定実行

### 4-2-1.ファイル指定

```bash
# テンプレート
golangci-lint run ファイル名

# 例
golangci-lint run main.go
```

### 4-2-2.ディレクトリ指定

```bash
# テンプレート
golangci-lint run ディレクトリ名

# 例
golangci-lint run dir1
```

### 4-2-3.ディレクトリ指定【再帰的ver】

```bash
# テンプレート
golangci-lint run ディレクトリ名/...

# 例
golangci-lint run dir2/...
```

## 4-3. Linter設定

### 4-3-1.有効なLinterと使用可能なLinterの閲覧

```bash
golangci-lint help linters

golangci-lint linters
```

### 4-3-2.特定のリンターだけ有効にして実行

```bash
golangci-lint run --disable-all --enable errcheck
```

### 4-3-3.特定のリンターを無効

```bash
golangci-lint run --disable golint
```

### 4-3-4.複数のリンターを有効/無効にする

```bash
golangci-lint run --enable errcheck,govet --disable golint
```

# 【5.設定ファイル】

golangci-lintはあらかじめファイルで設定した内容を実行できます。

## 5-1. 設定ファイルの種類

- `.golangci.yml`
- `.golangci.yaml`
- `.golangci.toml`
- `.golangci.json`

## 5-2. YAMLの書き方

### 5-2-1. 全体

```yaml
# 解析時に使用するLinterを設定
linters:
  option: value
# linterそれぞれの詳細設定
linters-settings:
  option: value
# 解析で検出された問題(issues)の扱いの設定
issues:
  option: value
# 出力結果のフォーマット、出力先設定
output:
  option: value
# 解析時の動作設定
run:
  option: value
# 解析で検出された問題(issues)の重要度の設定
severity:
  option: value
```

### 5-2-2. lintersセクション

```yaml
linters:
  # 全てのLinterを無効化する
  disable-all: true
  # disable-allで無効化した後、個別でLinterを有効化する
  enable:
    - asasalint
    - asciicheck
  # 全てのLinterを有効化する
  enable-all: true
  # enable-allで有効化した後、個別でLinterを無効化する
  disable:
    - asasalint
    - asciicheck
  # あらかじめ用意されているlinterセット（プリセット）を有効化する
  # linterセット（プリセット）に設定されているLinterが一括で有効化される
  presets:
    - bugs
    - comment
  # 有効なlinterで実行速度が速いものだけを対象とする設定
  fast: true
```

### 5-2-3. linters-settingsセクション

以下のドキュメントで使用したいLinterの設定方法を参照してください。

https://golangci-lint.run/usage/linters/

### 5-2-4. issuesセクション

```yaml
issues:
  # 検出された問題(issues)の文で、正規表現でマッチするものを出力から除外する
  exclude:
    - abcdef
  # パス、使用linter、テキスト、ソース毎に除外対象を設定
  exclude-rules:
    # 「_test\.go」にマッチするファイルは「gocyclo, errcheck」の検出対象外
    - path: _test\.go
      linters:
        - gocyclo
        - errcheck
    # internal/hmac/ 内でテキストに "weak" を含む場合、gosec の警告を除外
    - path: internal/hmac/
      text: "weak"
      linters:
        - gosec
    # lll の問題で、ソースコードが ^//go:generate で始まる場合は除外
    - linters:
        - lll
      source: "^//go:generate "
  # デフォルトの除外パターンの有効化設定
  exclude-use-default: false
  # exclude、exclude-rulesの正規表現を大文字小文字区別するかの設定
  exclude-case-sensitive: false
  # 指定ディレクトリ内のファイルのissueを警告から除外
  exclude-dirs:
    - src/external_libs
    - autogenerated_by_my_lib
  # vendor、testdata等の一般的に除外すべきディレクトリの除外設定
  exclude-dirs-use-default: false
  # 特定ファイルは解析するが、そのファイルのissueを出力対象から除外
  exclude-files:
    - ".*\\.my\\.go$"
    - lib/bad.go
  # 自動生成されたファイルの解析方法を設定
  exclude-generated: strict
  # デフォルトで除外されissueのIDを指定して有効化する
  include:
    - EXC0001
    - EXC0002
  # 1つのlinterごとに報告するissueの最大件数
  max-issues-per-linter: 0
  # 同一テキストを持つissueの報告件数を制限
  max-same-issues: 0
  # 出力されるissueを、行単位で一意にするかを指定
  uniq-by-line: false
  # 新しく追加されたissue(問題)のみ出力する
  new: true
  # Gitのmerge-base以降に発生したissueのみ出力
  new-from-merge-base: main
  # Gitの特定のリビジョン以降に作成されたissueのみを出力
  new-from-rev: HEAD
  # 指定されたパッチファイルに記載された変更箇所のみを対象にissueを出力
  new-from-patch: path/to/patch/file
  # 新規変更があったファイルの全体を出力するか、差分のみを出力するか設定
  whole-files: true
  # linterが対応している場合に、検出された問題を自動で修正
  fix: true
```

### 5-2-5. outputセクション

```yaml
output:
  # 出力フォーマット設定
  formats:
    # JSON形式の出力設定
    - format: json
      path: stderr
    # チェックスタイル形式の出力設定
    - format: checkstyle
      path: report.xml
     # カラーの行番号付き形式の出力設定
    - format: colored-line-number
  # 各issueの対象行のコードを一緒に出力する設定
  print-issued-lines: false
  # 各issueの末尾に使用Linter名を出力する設定
  print-linter-name: false
  # 出力されるファイルパスの先頭に接頭辞(プレフィックス)を追加する設定
  path-prefix: ""
  # 出力結果をソートするかの設定
  sort-results: true
  # ソートの優先順位を設定
  sort-order:
    # issueを検出したLinter名でソート
    - linter
    # 問題の重要度でソート
    - severity
    # ファイルパス、行、列の順でソート
    - file
  # 各Linter毎の統計情報を表示するか設定
  show-stats: true
```

### 5-2-6. runセクション

```yaml
run:
  # 解析実行のタイムアウト設定
  timeout: 5m
  # ファイルパスをどの基準にするかの設定
  relative-path-mode: gomod # go.modファイルのディレクトリを基準にする
  # 1つ以上のissueが検出された際に、出力される終了コードの設定
  issues-exit-code: 2
  # テストファイル（*_test.go）を解析対象に含めるかの設定
  tests: false
  # ビルドタグを指定し、条件付きコンパイルの有効化を設定
  build-tags:
    - mytag
  # Goモジュールの取得方法を設定
  modules-download-mode: readonly # 自動的なgo.modの更新を禁止し、変更が必要な場合エラーにする
  # golangci-lintを並列実行することを許可するかの設定
  allow-parallel-runners: true
  # 並行実行される場合に、ロックを用いて直列実行するかの設定
  allow-serial-runners: true
  # lint対象となるGoのバージョンを設定
  go: '1.19'
  # golangci-lintが同時に実行するOSスレッド数（GOMAXPROCS の設定）を設定
  concurrency: 4
```

### 5-2-7. severityセクション

```yaml
severity:
  # issueのデフォルト重要度を設定
  default-severity: error
  # 正規表現のマッチングで大文字小文字を区別するかの設定
  case-sensitive: true
  # 各Linterの個別のissueに対して重要度を上書きする設定
  rules:
    - linters:
        - dupl
      severity: info
```

# 【6.リンター 一覧】

## 6-1. デフォルトで有効なLinter

| 名前 | 説明 | おすすめ |
| --- | --- | --- |
| errcheck | エラーチェックしていない箇所を検出 |  |
| gosimple | 複雑な処理や不必要な処理を検出 | ◯ |
| govet | フォーマット文字列の不整合、誤った型の使用、意図しない挙動を検出 | ◯ |
| ineffassign | 不要な変数への代入、計算のミスを検出 |  |
| staticcheck | バグ、パフォーマンス問題、非効率な処理、冗長な表現など幅広い問題を検出 | ◯ |
| unused | 使用されていない変数や関数を検出 |  |

## 6-2. デフォルトで無効なLinter

| Linter名 | 説明 | おすすめ |
| --- | --- | --- |
| asasalint | 可変長引数（...any）を持つ関数に、[]any 型の値をそのまま渡している箇所を検出 |  |
| asciicheck | コード内の識別子がASCII文字のみで構成されていない箇所を検出 |  |
| bidichk | 危険なユニコード文字列が使用されている箇所を検出 |  |
| bodyclose | HTTPレスポンスのボディが正しく閉じられていない箇所を検出 | ◯ |
| canonicalheader | net/http.Headerが正規化されていない箇所を検出 |  |
| containedctx | 構造体内にcontext.Context型のフィールドが含まれている箇所を検出 | ◯ |
| contextcheck | 関数内で新たに生成されたコンテキストの誤用箇所を検出 |  |
| copyloopvar | ループ内でループ変数が不適切にコピーされる箇所を検出 |  |
| cyclop | 各関数やパッケージの循環的複雑度が閾値を超える箇所を検出 |  |
| decorder | 型・定数・変数・関数などの宣言順序や数が不適切な箇所を検出 | △ |
| depguard | インポートしたパッケージが許可リストに含まれていない箇所を検出 | ◯ |
| dogsled | 代入文において過剰な空白識別子が使用される箇所を検出 |  |
| dupl | コード中の重複した記述箇所を検出 | △ |
| dupword | 同一単語の不必要な重複箇所を検出 |  |
| durationcheck | duration同士の乗算箇所を検出 |  |
| err113 | 不適切なエラー処理箇所と方法を検出 | △ |
| errchkjson | JSONエンコーディングにおける不正な型使用や省略されたエラーチェック箇所を検出 |  |
| errname | 定数エラーの命名規則違反箇所を検出 |  |
| errorlint | エラーラッピング方式に問題をもたらすコード箇所を検出 | ◯ |
| exhaustive | 列挙型のswitch文で網羅性が不足している箇所を検出 |  |
| exhaustruct | 構造体の全フィールドが初期化されていない箇所を検出 |  |
| exptostd | golang.org/x/exp/内の関数が標準ライブラリ関数に置換可能な箇所を検出 |  |
| fatcontext | ループや無名関数内でcontextが入れ子になっている箇所を検出 |  |
| forbidigo | 禁止された識別子の使用箇所を検出 |  |
| forcetypeassert | 無理な型アサーション箇所を検出 |  |
| funlen | 非常に長い関数（行数が多い箇所）を検出 |  |
| gci | コードとインポート文の不適切なフォーマット箇所を検出 | △ |
| ginkgolinter | ginkgoおよびgomegaの使用が規定スタイルに沿っていない箇所を検出 |  |
| gocheckcompilerdirectives | //go:で始まるコンパイラディレクティブの形式不正箇所を検出 |  |
| gochecknoglobals | グローバル変数の使用箇所を検出 |  |
| gochecknoinits | init関数の使用箇所を検出 |  |
| gochecksumtype | sum typesの網羅性不足箇所を検出 |  |
| gocognit | 関数の認知的複雑度が高い箇所を検出 |  |
| goconst | 繰り返し使用される文字列リテラルの多用箇所を検出 |  |
| gocritic | バグ、パフォーマンス問題、スタイル違反箇所を検出 | ◯ |
| gocyclo | 循環的複雑度が高い箇所を検出 |  |
| godot | コメントがピリオドで終わらない箇所を検出 |  |
| godox | コメント内の注意喚起キーワード使用箇所を検出 | ◯ |
| gofmt | gofmtに沿わないコード整形箇所を検出 | ◯ |
| gofumpt | gofumpt整形ルール違反箇所を検出 |  |
| goheader | ファイルヘッダーのパターン不一致箇所を検出 |  |
| goimports | goimportsフォーマット違反箇所を検出 | ◯ |
| gomoddirectives | go.modディレクティブの不正使用箇所を検出 |  |
| gomodguard | 直接依存するGoモジュールのルール違反箇所を検出 |  |
| goprintffuncname | printf系関数の命名不備箇所を検出 |  |
| gosec | セキュリティ脆弱性箇所を検出 | ◯ |
| gosmopolitan | i18n・l10nに関するアンチパターン使用箇所を検出 |  |
| grouper | 式のグループ化不適切箇所を検出 |  |
| iface | 不適切なインターフェース利用箇所を検出 |  |
| importas | 不統一なインポートエイリアス使用箇所を検出 |  |
| inamedparam | パラメータ名未設定のインターフェースメソッド箇所を検出 |  |
| interfacebloat | インターフェースの肥大化箇所を検出 |  |
| intrange | 整数のrange利用が可能な箇所を検出 |  |
| ireturn | インターフェース受領時の具体型返却箇所を検出 |  |
| lll | 過度に長いコード行箇所を検出 |  |
| loggercheck | ロガーライブラリにおけるキー・値ペアの不正記述箇所を検出 | △ |
| maintidx | 保守性の低いコード箇所を検出 |  |
| makezero | 初期長がゼロ以外のスライス宣言箇所を検出 |  |
| mirror | 誤ったミラーパターン使用箇所を検出 |  |
| misspell | スペルミス箇所を検出 | ◯ |
| mnd | マジックナンバー使用箇所を検出 |  |
| musttag | 必要なタグ未付与箇所を検出 |  |
| nakedret | 不適切なnaked return使用箇所を検出 | ◯ |
| nestif | 深い入れ子のif文箇所を検出 |  |
| nilerr | nilチェックと矛盾するエラー返却箇所を検出 | ◯ |
| nilnesserr | nilチェック後に別のnilエラー返却箇所を検出 |  |
| nilnil | nilエラーと不正値の同時返却箇所を検出 |  |
| nlreturn | 不要な改行を含むreturn文箇所を検出 |  |
| noctx | HTTPリクエストでの不適切なcontext使用箇所を検出 |  |
| nolintlint | nolintコメントの不正記述箇所を検出 |  |
| nonamedreturns | 名前付き戻り値使用箇所を検出 |  |
| nosprintfhostport | Sprintfの不適切な使用箇所を検出 |  |
| paralleltest | t.Parallel()未呼び出し箇所を検出 | △ |
| perfsprint | fmt.Sprintfの高速代替可能箇所を検出 |  |
| prealloc | プリアロケーション可能なスライス宣言箇所を検出 |  |
| predeclared | プリデファイン識別子の再定義箇所を検出 |  |
| promlinter | 不適切なPrometheusメトリクス名箇所を検出 |  |
| protogetter | protoメッセージフィールドへの直接アクセス箇所を検出 |  |
| reassign | パッケージレベル変数の再代入箇所を検出 |  |
| recvcheck | 不適切なレシーバー型使用箇所を検出 |  |
| revive | コードスタイルや品質問題箇所を検出 | ◯ |
| rowserrcheck | SQL Rowsのエラーチェック不足箇所を検出 | ◯ |
| sloglint | log/slogのコードスタイル不整合箇所を検出 |  |
| spancheck | スパン設定・使用の誤り箇所を検出 |  |
| sqlclosecheck | データベースオブジェクトの不適切なクローズ箇所を検出 | ◯ |
| stylecheck | コードスタイルの不備箇所を検出 | △ |
| tagalign | 構造体タグの整列不備箇所を検出 |  |
| tagliatelle | 構造体タグの形式不正箇所を検出 |  |
| testableexamples | テスト可能なコード例の記述不備箇所を検出 |  |
| testifylint | testify使用の不備箇所を検出 |  |
| testpackage | テストコードが本体パッケージと分離されていない箇所を検出 |  |
| thelper | テストヘルパー内でのt.Helper()未呼び出し箇所を検出 |  |
| tparallel | テストコードにおけるt.Parallel()の使用不備箇所を検出 |  |
| unconvert | 不要な型変換箇所を検出 | ◯ |
| unparam | 未使用の関数パラメータ箇所を検出 | ◯ |
| usestdlibvars | 標準ライブラリの変数・定数利用可能箇所を検出 |  |
| usetesting | 適切なテスト関数への置換可能箇所を検出 |  |
| varnamelen | 不適切な変数名長箇所を検出 |  |
| wastedassign | 不要な代入箇所を検出 | △ |
| whitespace | 不必要な改行箇所を検出 | △ |
| wrapcheck | エラーラップ不備箇所を検出 | △ |
| wsl | 空行の不適切な変更箇所を検出 |  |
| zerologlint | zerologの不適切な使用箇所を検出 |  |
| tenv | 重複するlinter機能箇所を検出 |  |

# 【7. おすすめの設定】

以下はおすすめの設定です。デフォルトのリンター6種に加えて、基本的なことを解析するリンターを追加しています。また、以下の設定だとテスト系のコードの解析はしないような設定にしています。

【.golangci.yaml】

```yaml
linters:
  disable-all: true
  enable:
    - bodyclose # HTTPレスポンスのボディが正しく閉じられていない箇所を検出
    - containedctx # 構造体内にcontext.Context型のフィールドが含まれている箇所を検出
    - depguard # インポートしたパッケージが許可リストに含まれていない箇所を検出
    - errcheck # [default]エラーチェックしていない箇所を検出
    - errorlint # エラーラッピング方式に問題をもたらすコード箇所を検出
    - gocritic # バグ、パフォーマンス問題、スタイル違反箇所を検出
    - godox # コメント内の注意喚起キーワード使用箇所を検出
    - gofmt # gofmtに沿わないコード整形箇所を検出
    - goimports # goimportsフォーマット違反箇所を検出
    - gosec # セキュリティ脆弱性箇所を検出
    - gosimple # [default]複雑な処理や不必要な処理を検出
    - govet # [default]Goの公式リンター フォーマット文字列の不整合、誤った型の使用、意図しない挙動を検出
    - ineffassign # [default]不要な変数への代入、計算のミスを検出
    - misspell # スペルミス箇所を検出
    - nakedret # 不適切なnaked return使用箇所を検出
    - nilerr # nilチェックと矛盾するエラー返却箇所を検出
    - revive # コードスタイルや品質問題箇所を検出
    - rowserrcheck # SQL Rowsのエラーチェック不足箇所を検出
    - sqlclosecheck # データベースオブジェクトの不適切なクローズ箇所を検出
    - staticcheck # [default]バグ、パフォーマンス問題、非効率な処理、冗長な表現など幅広い問題を検出
    - unconvert # 不要な型変換箇所を検出
    - unparam # 未使用の関数パラメータ箇所を検出
    - unused # [default]使用されていない変数や関数を検出

linters-settings:
  depguard:
    rules:
      main:
        deny:
          - pkg: io/ioutil
            desc: The io/ioutil package has been deprecated, see https://go.dev/doc/go1.16#ioutil
  revive:
    rules:
      - name: package-comments  # パッケージ/関数コメント disable
        disabled: true
  godox:
    # 検出対象となるキーワードのリスト
    keywords:
      - "TODO"

issues:
  exclude-use-default: false
  max-issues-per-linter: 0
  max-same-issues: 0

output:
  formats:
    - format: colored-line-number
  print-linter-name: true

run:
  timeout: 5m
  tests: false
  modules-download-mode: readonly
  go: '1.24.1'

severity:
  default-severity: error
```

# 【8.VSCodeの設定】

## 8-1. 推奨設定

以下を「.vscode/settings.json」に記述することが推奨されています。

```json
{
	"go.lintTool": "golangci-lint",
	"go.lintFlags": [
		"--fast"
	]
}
```

## 8-2. 設定の解説

### 8-2-1. go.lintTool

Goのリントにgolangci-lintを使用することを指定します。

編集しているファイルに対して自動的に `.golangci.yml` という設定ファイルを検出します。そのため、VSCodeで再度個別に設定を行う必要がありません。

### 8-2-2. go.lintFlags

解析時に—fastオプションをつけることで解析を高速化します。

※ `--fast` オプションを指定せず、エディター上で実行すると、エディターがフリーズしてしまう可能性があります。

# 【9.CI(継続的インテグレーション)導入】

## 9-1. CI(Continuous Integration)とは

CIとは開発時にビルドやテストを自動で実行するプラクティスです。

開発者がコードを修正し、Githubなどのバージョン管理システムにマージするのをトリガーに実行され、テストが失敗していないか、ビルドが壊れていないかを自動で確認できます。

## 9-2. Github Actionsでの導入

Github Actionsでは、「.github/workflows」配下に適当なYAMLファイルを格納するだけで動作します。以下がgolangci-lintによるリンターを実行する設定の例です。

【.github/workflows/golangci-lint.yaml】

```yaml
# ワークフロー名
name: golangci-lint
# トリガー設定
on:
  push: # リポジトリへのプッシュ時
  pull_request: # プルリクの作成・更新時

# リポジトリの読み取り権限を付与
permissions:
  contents: read

jobs:
  golangci:
    name: lint # job名
    runs-on: ubuntu-latest # jobの実行環境設定
    steps:
      # リポジトリからソースコードを取得
      - name: Checkout Repository
        uses: actions/checkout@v4
 
      # 解析で使用するGoのセットアップ
      - name: Go Setup
        uses: actions/setup-go@v5
        with:
          go-version: 1.24.1

      # golangci-lintの実行
      - name: golangci-lint
        uses: golangci/golangci-lint-action@v6
        with:
          version: v1.64
```

【プルリクでの出力結果】

![スクリーンショット 2025-03-22 18.43.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247925/25183b0f-6805-4573-a527-a0963ea6e731.png)
![スクリーンショット 2025-03-22 18.45.01.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247925/fd98ed5e-e9e7-4b30-9799-97675d55918c.png)
![スクリーンショット 2025-03-22 18.44.26.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247925/777675cf-df66-4f92-a2b3-a51d126c70af.png)


## 9-3. 検出内容をプルリクコメントで出力

Reviewdogというツールを使用し、Reviewdog 経由でgolangci-lintを実行することで、リント結果をプルリクのレビューコメントとして出力することができます。リント結果はプルリクないの差分にのみコメントされ、設定によっては無視してマージでできるので、リンターで縛りすぎたくない場合にもおすすめです。

レビューコメントの内容を修正して、プッシュすると自動でレビューコメントは消えます。

以下がReviewdog 経由でgolangci-lintを実行する設定の例です。

【.github/workflows/golangci-lint.yaml】

```yaml
name: golangci-lint
on:
  push:
  pull_request:

permissions:
  checks: write        # リント結果の表示権限
  contents: read       # リポジトリのファイルの読み取り権限
  pull-requests: write # プルリクにコメントする権限

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      # リポジトリからソースコードを取得
      - name: Checkout Repository
        uses: actions/checkout@v4

      # Reviewdogによるgolangci-lintの実行
      - name: Run golangci-lint with Reviewdog
        uses: reviewdog/action-golangci-lint@v2
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}     # GithubAPI実行用のトークン設定
          go_version: 1.24.1                            # 解析に使用するGoバージョン設定
          reporter: github-pr-review                    # リント結果をレビューとして出力する設定
          level: warning                                # 検出されたissueのレベルをwarningにする設定
          # workdir: go_practice/                       # リント対象のフォルダを設定
          golangci_lint_flags: "--config=.golangci.yaml" # .golangci.ymlの内容でリントを実行させる設定
```

【プルリクでの出力結果】

![スクリーンショット 2025-03-22 18.53.25.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1247925/0418f5d2-2729-4257-80f4-7ff58f7b73f9.png)