$shibayu36->blog;

クラスター株式会社のソフトウェアエンジニアです。エンジニアリングや読書などについて書いています。

新規プロジェクトにgolangci-lintを導入したメモ

MQTT+Protocol Buffersを使ってリアルタイムに2次元位置を同期するサーバーを書いてみたで作ったレポジトリにgolangci-lintを導入したのでメモ。

以下の資料を参考にした。

今回は、新規プロジェクトで、かつ、できる限り厳しくチェックしてgolangの書き方に対してフィードバックを受けたかった。そこで以下のような作戦にした。

  • enable-all: trueを設定し、全チェックする
  • 不要なチェックは明示的にdisableやexcludeの設定をする
  • CIでチェックする

まずは.golangci.ymlでenable-allして明示的に除外ルールを書く。これで手元でgolangci-lint runするだけでlintできるようになる。

linters:
  enable-all: true
  disable:
    - wsl # 余計な改行をなるべく含まないようにすることで得られる見通しの良さを重視するため
    - nlreturn # 上記と同様
    - depguard # 規模的に依存関係の流れを厳格に管理する必要性はないため
    - godot # dot強制しなくていい
    - mnd # 多少マジックナンバーがあってもいい
    - err113 # 多少動的なerrがあってもいい
    - paralleltest
    - perfsprint # パフォーマンスチューニングはここまで求められていない

linters-settings:
  cyclop:
    max-complexity: 16
  revive:
    rules:
      - name: var-naming
        severity: warning
        disabled: false
      - name: exported
        severity: warning
        disabled: false
  gosec:
    excludes:
      - G115 # pbへの変換でint -> int32への変換が多いため
  exhaustruct:
    exclude:
      - '.+/shared\.PlayerState$'

issues:
  exclude-rules:
    # Exclude some linters from running on tests files.
    - path: _test\.go
      linters:
        - gocyclo
        - gosec
        - exhaustruct
    # Exclude protobuf generated files from linting
    - path: shared/proto/*.pb.go
      linters:
        - all

run:
  timeout: 5m

さらにGitHub Actionsでlintを動かすために、.github/workflows/lint.ymlを設定する。setup-goにgo-version-fileを渡せるのが便利。

name: Lint

on:
  push:
    branches:
      - main
  pull_request:

jobs:
  golangci:
    name: lint
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4

      - name: Set up Go
        uses: actions/setup-go@v5
        with:
          go-version-file: "go.mod"

      - name: golangci-lint
        uses: golangci/golangci-lint-action@v6
        with:
          version: latest
          args: --timeout=5m

このように設定したら新規プロジェクトだけどめちゃくちゃ怒られてgolangの勉強が捗った。便利。