7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

golangci-lintとは?

Goのlintツールです。

lintツールはlinterとしても呼ばれ、プログラムのソースコードの静的解析を行い、潜在的なバグを引き起こしそうなコードの発見やコードの命名等が規則に沿っているかどうかを指摘や修正等を行えます。

golangci-lintを使用するメリット

linterは基本的にコードの品質を高めるために使われます。

コードの品質とは

コードの効率性、読みやすさ、使いやすさを示す指標のことをコードの品質と言います。

コードの品質を高めることで、他の人がコードを読む時間を節約し、なおかつ冗長なコードを減らすことができ、時間とリソースの節約をすることができます。

golangci-lintは、コードの命名規則だけでなく、バグを引き起こしそうなコード、エラーハンドリングしていないコードなど、設定すれば多くのコードの書き方にかける規則の指摘をしてくれます。

加えて、オプションを使えば修正も行なってくれるので、コードレビューをある程度自動化することができます。

インストール

homebrewでは次のコマンドでインストールします。

zsh
brew install golangci-lint

GOPATHでは下のコマンドでインストールします。

zsh
go install github.com/golangci/golangci-lint/cmd/golangci-lint@v1.61.0

lintを走らせる

下のコマンドで走らせることができます。

zsh
golangci-lint run

もし走らせて、構文エラーがあった場合、下のようにerrを返していないところなどを教えてくれます。

zsh
❯ 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を作成して、下のように記述します。

./config/.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を記述しました。

.github/workflows/golint.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: writepull-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等で下のように表示してくれます。
スクリーンショット 2024-11-24 7.32.07.png

golangci-lintを使うことでコードの品質を上げ、共同開発の効率を上げてくれます。

ぜひ活用してみてください!

7
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?