メインコンテンツへスキップ

Go Proposal Weekly Digest

Go言語のproposal更新を毎週お届け

#35487accepted

x/tools/go/analysis/vet: export cmd/vet and cmd/fix's \\[]\\*Analyzer suites

ステータス変更: likely_accept accepted

要約

AIによる要約であり、誤りを含む場合があります。

概要

cmd/vet および cmd/fix が内部で使用しているアナライザ一覧([]*analysis.Analyzer)を、golang.org/x/tools/go/analysis/suite/vet および golang.org/x/tools/go/analysis/suite/fix という新規パッケージに公開するproposalです。これにより、ユーザーが独自の静的解析ツールを構築する際に、既存のvetおよびfixのアナライザセットを再利用しやすくなります。

ステータス変更

likely_acceptaccepted
2026年5月21日の週次Proposalレビューミーティングにおいて、@aclements が前週の likely_accept から合意に変更がないと判断し、正式に accepted と決定しました。実装CLとして go.dev/cl/780780(x/toolsサイドの新パッケージ作成)と go.dev/cl/780900(cmd/vet・cmd/fix側での利用)がすでに提出されており、実装フェーズに移行しています。

技術的背景

現状の問題点

cmd/vet/main.go に定義されているアナライザリストはパッケージ内部のプライベートな定義であり、外部から参照できません。そのため、go vet と同じアナライザセットを含む独自のマルチチェッカーを作りたい開発者は、ソースコードを参照して手動でリストをコピーするしかありませんでした。

// cmd/vet/main.go の内部定義(現状・公開されていない)
var analyzers = []*analysis.Analyzer{
    appends.Analyzer,
    asmdecl.Analyzer,
    assign.Analyzer,
    atomic.Analyzer,
    // ... 多数のアナライザ
}

このリストはGoのバージョンアップに伴い変化するため、コピーしたリストは陳腐化するリスクがあります。

提案された解決策

golang.org/x/tools/go/analysis/suite/vet および golang.org/x/tools/go/analysis/suite/fix という2つのパッケージを新規作成し、それぞれ var Suite = []*analysis.Analyzer{ ... } を公開します。

// golang.org/x/tools/go/analysis/suite/vet
package vet
import "golang.org/x/tools/go/analysis"
// Suite は cmd/vet が実行するアナライザのセットです。
var Suite = []*analysis.Analyzer{ ... }
// golang.org/x/tools/go/analysis/suite/fix
package fix
import "golang.org/x/tools/go/analysis"
// Suite は cmd/fix が実行するアナライザのセットです。
var Suite = []*analysis.Analyzer{ ... }

cmd/vetcmd/fix 自身も、これらの新パッケージを参照して実装されます(CL 780900)。vetfix を同一パッケージにまとめる案も検討されましたが、不要なimport依存が生じるため、別パッケージとする設計が採用されました。

これによって何ができるようになるか

go vet のアナライザセットをベースにした独自解析ツールを、コピー&ペーストなしに構築できます。

コード例

// Before: 従来のワークアラウンド(vet のアナライザを手動でコピー)
import "golang.org/x/tools/go/analysis/multichecker"
func main() {
    multichecker.Main(
        appends.Analyzer,
        asmdecl.Analyzer,
        assign.Analyzer,
        // ... vet のリストを手動でコピー(陳腐化リスクあり)
        myCustomAnalyzer,
    )
}
// After: 新パッケージを使った書き方
import (
    "golang.org/x/tools/go/analysis/multichecker"
    vetSuite "golang.org/x/tools/go/analysis/suite/vet"
)
func main() {
    analyzers := append(vetSuite.Suite, myCustomAnalyzer)
    multichecker.Main(analyzers...)
}

議論のハイライト

  • パッケージ名の変遷: 当初は x/tools/go/analysis/vet、次に x/tools/go/analysis/passes/suite/{fix,vet} が提案されましたが、最終的にレビューミーティングで passes セグメントを除いた x/tools/go/analysis/suite/{fix,vet} に決定されました。
  • 可変グローバル変数の懸念: @prattmic が var Suitefunc Suite() にすべきではないかと提案しました。init() 内で Suite を改変するアナライザが生じうる点が指摘されましたが、@adonovan は「自作のアナライザがリンクされるにはmainパッケージで明示的に指定される必要があり、リスクは低い」と判断し、変数のままとすることになりました。
  • 重複アナライザの扱い: 関連issue #75227 において、パッケージ自身が重複アナライザを自動除去するか、ユーザーに委ねるかが議論されましたが、今回の設計ではシンプルなスライス公開にとどめています。
  • vetとfixのアナライザ分離: go vetgo test が実行するアナライザのセットは異なる場合があるため(#47309 参照)、個別のパッケージとして管理することで柔軟な組み合わせが可能になります。
  • 6年以上のラグ: このissueは2019年11月に提出されながら、2025年5月の @adonovan による具体的なAPI提案まで実質的な議論が進まず、2026年5月に承認に至りました。

関連リンク