debug/pe: deprecate ImportDirectory
要約
概要
debug/pe パッケージの ImportDirectory 型を正式に非推奨(Deprecated)にする提案です。この型は約15年前に追加されましたが、公開APIのどこからも返されないため、利用者にとって実質的に使い道がありません。
ステータス変更
likely_accept → accepted
likely accept の段階から反対意見が出なかったため、@aclements が proposal review group を代表して「No change in consensus」として承認しました。変更はドキュメントへの Deprecated: 注記だけで、既存コードの動作には影響しません。後方互換性の点でも論点がほとんどないため、短期間で承認されたと考えられます。提案者は @cherrymui で、Windows チーム(@golang/windows)と、debug/pe を長く保守してきた @alexbrainman に cc されています。
技術的背景
現状の問題点
ImportDirectory は PE(Windows の実行ファイル形式)のインポートディレクトリテーブルの1エントリを表す構造体です。2011年頃に説明なしで追加されました。
// TODO(brainman): document ImportDirectory once we decide what to do with it.
type ImportDirectory struct {
OriginalFirstThunk uint32
TimeDateStamp uint32
ForwarderChain uint32
Name uint32
FirstThunk uint32
dll string
}
主な問題は次の3点です。
- この型は
File.ImportedSymbols()の内部で一時的に使われるだけです。Fileなどの公開APIから値を取得する手段がありません。 - 非公開フィールド
dllを含むため、利用者が自分で正しく値を組み立てることもできません。 - 2016年の #15345(
cmd/linkから使えるようdebug/peを拡張する作業)の頃から「扱いを決めたらドキュメント化する」という TODO が残ったままでした。
2025年には、この型の各フィールドに詳しい説明を付ける CL 679457 が投稿されました。これに対し @alexbrainman は #15345 で次のように指摘しています。「この構造体は何の役にも立たない。GitHub を検索しても有用な利用例は見つからなかった。削除できないなら deprecated と書くべきだ」。
提案された解決策
Go 1 互換性の約束があるため、型は削除せず、doc コメントに Deprecated: を付けます。実装 CL 813961 の内容は次のとおりです。
// ImportDirectory represents an entry in a PE file's import directory table.
//
// Deprecated: ImportDirectory is an internal detail and should not be used directly.
type ImportDirectory struct { ... }
あわせて api/next に pkg debug/pe, type ImportDirectory //deprecated を追加し、リリースノートには「誤ってエクスポートされた内部実装の詳細である」と記載します。
これによって何ができるようになるか
新しい機能は追加されません。主な効果は次のとおりです。
staticcheckや gopls が非推奨型の使用を警告するため、使い道のない型に頼るコードを書かずに済みます。- pkg.go.dev 上で非推奨として目立たない表示になり、
debug/peの API の見通しが良くなります。 - 長年残っていた TODO が片付き、「この型は何のためにあるのか」という混乱がなくなります。
インポート情報が欲しい場合は、従来どおりFile.ImportedSymbols()とFile.ImportedLibraries()を使います。
コード例
// Before: ImportDirectory を使おうとしても、File から取得する API がない
var dir pe.ImportDirectory // 値を得る手段がなく、dll フィールドも設定できない
_ = dir.FirstThunk
// After: ImportDirectory は Deprecated。公開 API を使う
f, err := pe.Open("app.exe")
if err != nil {
log.Fatal(err)
}
defer f.Close()
syms, err := f.ImportedSymbols() // 例: "CreateFileW:kernel32.dll"
if err != nil {
log.Fatal(err)
}
for _, s := range syms {
fmt.Println(s)
}
議論のハイライト
- この型は2011年の CL で説明なしに追加されました。2016年の CL 22182 で、扱いを決めるための TODO が付けられています。
- @alexbrainman は「本来はとうに削除すべきだったが、公開型なので削除できない」と述べ、削除の代わりに非推奨化を提案しました。
- フィールドを詳しく説明する CL 679457 という代替案もありました。ただし、使い道のない型を丁寧に文書化するより非推奨にするほうが適切、という方向でまとまりました。
- GitHub のコード検索でも有用な利用例は見つからず、非推奨化による実害はほぼないと判断されています。
- issue 上で目立った反対意見はなく、likely accept から accepted へそのまま進みました。