#63477active
go/types.ImportFunc
新規提案
要約
AIによる要約であり、誤りを含む場合があります。
概要
go/types パッケージに、関数値をそのまま types.Importer インターフェースとして使えるアダプタ型 ImporterFunc を追加する提案です。net/http の http.HandlerFunc と同じ仕組みです。Issueのタイトルは ImportFunc ですが、本文で提案されている型名は ImporterFunc です。
ステータス変更
(新規) → active
2023年10月に @adonovan が提出しました。その直後に @rsc が「#47487(関数値を単一メソッドのインターフェースへ変換できるようにする言語変更)が承認されれば、この型は不要になる。それまでは各所の非公開実装でしのげばよい」とコメントし、議論はそこで止まっていました。その後 #47487 は2026年7月に declined(却下)となりました。言語側での解決がなくなったため、ライブラリ側で対応するこの提案が再び検討対象になり、2026年11月に proposal review meeting の active 列に追加されたと考えられます。
技術的背景
現状の問題点
型チェッカー(types.Config)には、import されたパッケージを解決するための Importer を渡す必要があります。
type Importer interface {
Import(path string) (*Package, error)
}
実際のツールでは「パス → *types.Package」の対応表をすでに持っていることが多く、クロージャを1つ渡せば足ります。それでも Importer を満たすには毎回アダプタ型を自前で定義しなければなりません。提案者によると、golang.org/x/tools の中だけでも次の7箇所に、同じ importerFunc 型が重複して定義されています。
go/analysis/unitchecker(本体とテスト)go/analysis/passes/cgocallgo/packagesgopls/internal/lsp/cacheinternal/gcimporterのテストinternal/refactor/inlineのテスト
提案された解決策
// An ImporterFunc is an implementation of the single-method
// types.Importer interface based on a function value.
type ImporterFunc func(path string) (*types.Package, error)
func (f ImporterFunc) Import(path string) (*types.Package, error) { return f(path) }
これによって何ができるようになるか
- 静的解析ツール:
go/packagesで読み込んだ依存パッケージのマップを引くクロージャを、そのままtypes.Config.Importerに渡せます。 - テストコード: テスト用に用意したパッケージを返すだけの簡単なインポータを、1行で書けます。
- gopls や unitchecker などの基盤ツール: 重複しているアダプタ型を標準の型に置き換え、ボイラープレート(毎回書く定型コード)を減らせます。
コード例
// Before: パッケージごとにアダプタ型を自前で定義する
type importerFunc func(path string) (*types.Package, error)
func (f importerFunc) Import(path string) (*types.Package, error) { return f(path) }
conf := types.Config{
Importer: importerFunc(func(path string) (*types.Package, error) {
if p, ok := deps[path]; ok {
return p, nil
}
return nil, fmt.Errorf("no package %q", path)
}),
}
// After: 標準の型を使う
conf := types.Config{
Importer: types.ImporterFunc(func(path string) (*types.Package, error) {
if p, ok := deps[path]; ok {
return p, nil
}
return nil, fmt.Errorf("no package %q", path)
}),
}
議論のハイライト
ImporterFrom版を求める意見(@mvdan):types.ImporterFromを実装しているとImportは呼ばれないため、vendor を考慮できるImportFrom(path, dir, mode)向けのImporterFromFuncを追加すべきではないか、という提案がありました。garble でも同様の実装を使っているそうです。- 反論(@findleyr): 一般的なケースでは、
go/packagesなどで読み込み済みのため、パスとパッケージの対応はすでに決まっています。そのため、単純なImporterFuncの方が役に立つ場面が多いと述べました。 - 言語変更待ち(@rsc): #47487 が承認されれば
types.Importer(func...)と直接変換できるようになり、この型は不要になるとして、判断を先送りしました。 - #47487 の却下: 関連する「interface literals」の提案(#25860)の方が有力だとされ、#47487 は2026年7月に却下されました。@adonovan は、
WriterFuncのような標準のアダプタ型の追加は #25860 の結論が出るまで控えたいとも述べています。このため、今回の提案でも #25860 との関係が論点になる可能性があります。