staticcheck は Go コードの広範な静的解析を行うツールです。バグの検出、非推奨 API の使用、コードの簡略化提案など多岐にわたるチェックを提供します。
解決する問題
go vet だけでは検出できないバグや非効率なコードパターンが数多く存在します。staticcheck は 150 以上のチェックを備え、到達不能コード、非推奨 API の使用、不正な正規表現、不要なコード、パフォーマンス改善の余地などを検出します。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
|
func example() { re := regexp.MustCompile("[invalid")
var u uint if u >= 0 { fmt.Println("always true") }
io.ReadAll(strings.NewReader("test")) _ = re }
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| func example() { re := regexp.MustCompile(`[a-z]+`)
var u uint if u > 0 { fmt.Println("positive") }
data, _ := io.ReadAll(strings.NewReader("test")) _ = re _ = data }
|
設定
公式ドキュメント
1 2 3 4 5 6 7 8 9 10 11 12
| version: "2"
linters: enable: - staticcheck settings: staticcheck: checks: - all - "-ST1000" - "-ST1003"
|
オプション
| オプション |
型 |
デフォルト |
説明 |
checks |
[]string |
[all, -ST1000, -ST1003, -ST1016, -ST1020, -ST1021, -ST1022] |
有効化するチェックのリスト。all で全有効化し、- プレフィックスで個別に無効化 |
initialisms |
[]string |
[ACL, API, ASCII, ...] |
イニシャリズムとして扱う単語のリスト |
dot-import-whitelist |
[]string |
[] |
ドットインポートを許可するパッケージ |
http-status-code-whitelist |
[]string |
[200, 400, 404, 500] |
マジックナンバーチェックから除外する HTTP ステータスコード |
主要なチェックカテゴリ
SA: 静的解析(バグ検出)
| チェック |
検出内容 |
| SA1000 |
不正な正規表現 |
| SA1006 |
Printf に動的な第一引数を渡している |
| SA1012 |
nil の context.Context を渡している |
| SA1019 |
非推奨の関数・変数・定数の使用 |
| SA2000 |
sync.WaitGroup.Add がゴルーチン内で呼ばれている |
| SA4003 |
常に true/false になる比較 |
| SA4006 |
代入した値が使われていない |
| SA4010 |
*append の結果が使われていない |
| SA5001 |
defer 内で Body.Close が呼ばれているがエラーチェック前 |
| SA6005 |
strings.ToLower で比較する代わりに strings.EqualFold を使うべき |
| SA9003 |
空の分岐 |
S: コード簡略化
| チェック |
検出内容 |
| S1000 |
単一ケースの select を使うべき |
| S1001 |
for + copy の代わりに copy を使うべき |
| S1005 |
不要な _ 代入 |
| S1007 |
正規表現の raw string 使用を推奨 |
| S1025 |
fmt.Sprintf("%s", x) の不要な使用 |
| S1028 |
errors.New(fmt.Sprintf(...)) の代わりに fmt.Errorf を使うべき |
ST: スタイル
| チェック |
検出内容 |
| ST1000 |
パッケージコメントがない |
| ST1003 |
命名規則(MixedCaps)に違反 |
| ST1005 |
エラー文字列が大文字で始まっている |
| ST1006 |
レシーバ名が不適切 |
| ST1008 |
error が最後の戻り値でない |
QF: クイックフィックス
| チェック |
検出内容 |
| QF1001 |
if-else を switch に変換可能 |
| QF1003 |
if-else を strings.EqualFold に変換可能 |
| QF1011 |
冗長な型変換 |
サンプル
検出例
1 2 3 4 5 6 7 8 9 10 11 12
| data, _ := ioutil.ReadAll(resp.Body)
err := errors.New(fmt.Sprintf("user %s not found", id))
result, err := fetchData() result = nil
return fmt.Errorf("User not found")
|
修正例
1 2 3 4 5 6 7 8
| data, _ := io.ReadAll(resp.Body)
err := fmt.Errorf("user %s not found", id)
result, err := fetchData() _ = result
return fmt.Errorf("user not found")
|
注意点
- golangci-lint の
standard デフォルトセットに含まれている。明示的に有効化しなくてもデフォルトで動作する
- デフォルトで一部の ST(スタイル)チェックが無効化されている。厳格にするなら
checks: [all] で全有効化する
GL_DEBUG=staticcheck golangci-lint run --enable=staticcheck で有効なチェックの一覧を確認できる
- staticcheck は独自の設定ファイル(
staticcheck.conf)も持つが、golangci-lint 経由では .golangci.yml 内で設定する
参考リンク