doc: clarify if simple helper methods on x/sys syscall data structures require a proposal
要約
概要
golang.org/x/sys/windows パッケージにおいて、システムコールのデータ構造に対するシンプルなヘルパーメソッドの追加がGoのproposal(提案)プロセスを必要とするかどうかを明確化するドキュメント整備のproposalです。レビュー担当者間で異なる判断が下されていた状況を解消し、x/sys/windows パッケージのAPI追加ポリシーを公式ルールとして策定・承認しました。
ステータス変更
likely_accept → accepted
2026年4月15日の週次Proposalレビュー会議(@aclements, @adonovan, @cherrymui, @griesemer, @ianlancetaylor, @neild, @rolandshoemaker 参加)において、前回の「likely accept」から反対意見なしとして正式に承認されました。既存のメンテナー(@alexbrainman, @qmuntal)との丁寧な合意形成の末、明確なポリシーが確立されたことが決定の根拠です。
技術的背景
現状の問題点
golang.org/x/sys/windows パッケージへのAPI追加に関して、レビュー担当者ごとに判断が異なるという問題がありました。
具体的には、提案者(@database64128)が作成した2つのCLで正反対の指摘を受けました。
- CL 695195:レビュアーがヘルパーメソッドの追加を積極的に推奨
- CL 744880:別のレビュアー(@alexbrainman)がヘルパーメソッドをproposal不要な「架空のAPI」として削除を要求
問題となったのは以下のようなコードです。Windows APIのMIB_IF_TABLE2構造体にはRows()に相当するメソッドが存在しないため、Goで追加するとその分がWindows公式APIとの1対1マッピングから外れます。
// Windows APIの構造体をGoに移植した型
type MibIfTable2 struct {
NumEntries uint32
Table [1]MibIfRow2
}
// Goの慣用表現としてのヘルパーメソッド(Windows APIには存在しない)
func (t *MibIfTable2) Rows() []MibIfRow2 {
return unsafe.Slice(&t.Table[0], t.NumEntries)
}
Rows() は unsafe.Slice を内部で使うことで安全なスライスアクセスを提供しますが、これはWindows公式APIには定義されていない「付加的なAPI」です。
提案された解決策
x/sys/windows パッケージのAPI追加に対し、以下のルールをドキュメントとして明文化することが提案・承認されました。
ルール(承認済み):
- WindowsのAPIとGoのAPIとの間に明確な1対1マッピングがある場合は、proposalレビューなしで追加可能
- 1対1マッピングかどうかの判断は
golang.org/x/sys/windowsのメンテナー(@alexbrainman, @qmuntal)に委ねる - Windows API上に存在しないメソッドや型など、1対1マッピングを超えるAPIはGoのproposalプロセスを経る必要がある
これによって何ができるようになるか
このルール整備により、x/sys/windows の開発ワークフローが改善されます。
- Windows APIの直接移植(関数・構造体・定数)は
mkwinsyscallツールで自動生成され、proposalなしでCLにマージできる - 一方、
MibIfTable2.Rows()のような安全なスライスアクセスヘルパーはproposal提出が求められ、意図せぬAPIのバグリスクを事前に審査できる - レビュアーが毎回個人の判断に頼る必要がなくなり、一貫したコードレビューが可能になる
// Before: ルールが曖昧だったため、レビュアーによって判断が異なっていた
// あるレビュアー: "Rows()を削除してください(proposal必要)"
// 別のレビュアー: "Rows()を追加してください(推奨)"
// After: 明確なルールに基づいた判断が可能
// Windows公式APIと1対1対応 → proposal不要
func GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error)
type MibIfTable2 struct { NumEntries uint32; Table [1]MibIfRow2 }
// Windows APIに存在しないメソッド → proposal必要
func (t *MibIfTable2) Rows() []MibIfRow2 { ... }
議論のハイライト
- Unix系との非対称性: @ianlancetaylor はUnix系ではCヘッダファイルと同名・同機能のAPIはproposal不要と説明したが、Windowsの扱いは不明確であることを認めた。これがこのissue開設の直接的な動機となった。
- 後方互換性への強い懸念: @alexbrainman は
golang.org/x/sys/windowsにはセマンティックバージョニングがないため、一度追加したAPIは永久に変更不能であると強調した。過去にsyscall.Filetime.Nanoseconds()の戻り値がuint64であるべきところint64になってしまった事例を具体例として挙げた。 - 一貫性の問題:
Tokengroups・Tokenprivilegesなど7年前に追加されたヘルパーメソッドが既に存在しており、新規追加のRows()との扱いに矛盾があるとの指摘があった。@aclements は結果的にルール整備の必要性を認めた。 - proposalレビューの負荷問題: @aclements はproposalレビュー委員会の負荷軽減のため、安全なアクセサには一括事前承認を与えたかったと述べたが、メンテナー側の懸念を優先し最終的には「非1対1マッピングはproposal必要」に落ち着いた。また「trivial proposal track(軽量提案トラック)」という新たな仕組みの検討も言及した。
- 将来的な自動化: @qmuntal は長期的な解決策として #43838(
win32metadataを用いたAPIバインディング自動生成)を挙げたが、現時点では未実現であることを認めた。