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

Go Proposal Weekly Digest

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

#77887likely_accept

doc: clarify if simple helper methods on x/sys syscall data structures require a proposal

ステータス変更: active likely_accept

要約

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

概要

golang.org/x/sys/windows パッケージにおいて、Windows APIのデータ構造体に追加するシンプルなヘルパーメソッドが正式なproposalプロセスを必要とするかどうかを明確化し、その判断基準をドキュメントに記載することを求めるプロポーザルです。

ステータス変更

activelikely_accept
2026年4月8日の提案レビュー委員会会議において、メンテナーである @alexbrainman と @qmuntal の両者が合意した判断基準が妥当であるとの結論に至り、likely accept に移行しました。@aclements が承認基準の最終案をissueコメントとして明文化しました。

技術的背景

現状の問題点

golang.org/x/sys/windows パッケージへのCLレビューにおいて、ヘルパーメソッドの扱いを巡る矛盾が生じていました。

  • CL 695195 では、レビュアーがヘルパーメソッドを積極的に追加するよう促した
  • 続くCL 744880 では、別のレビュアー(@alexbrainman)がヘルパーメソッドの削除を要求した
    この不一致の根本原因は、proposalプロセスの文書が「新しいAPIには提案が必要」と定めているものの、x/sys/windows のような「OSのAPIをGoで表現する」という特殊な文脈への適用基準が不明瞭だったことにあります。
    問題となったコードの例を以下に示します。
// Windows API: GetIfTable2Ex / MIB_IF_TABLE2
func GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error)
type MibIfTable2 struct {
    NumEntries uint32
    Table      [1]MibIfRow2
}
// このRows()メソッドが「proposalが必要か不要か」が争点だった
func (t *MibIfTable2) Rows() []MibIfRow2 {
    return unsafe.Slice(&t.Table[0], t.NumEntries)
}

Rows() はWindows側のネイティブAPIには存在しないGoが独自に追加したメソッドです。一方で GetIfTable2ExMibIfTable2 自体はWindows公式APIの直接的な対応物であり、こちらにはproposalが不要とされてきました。この非対称性が混乱を招いていました。

提案された解決策

以下の明確な基準をドキュメントに記載します。

  • proposalが不要なもの: Windows APIとGoのAPIの間に明確な1対1の対応関係がある追加(生成ツール mkwinsyscall で生成される関数・型・定数など)。何が1対1の対応とみなされるかは golang.org/x/sys/windows のメンテナー(現在は @alexbrainman と @qmuntal)が判断する。
  • proposalが必要なもの: Windowsの公式APIに明確に対応しないAPI。具体的には、Windows側にはない独自のメソッド(上記の Rows() など)が含まれる。

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

この方針の明確化により、golang.org/x/sys/windows へのコントリビューターとレビュアー双方が、どのAPIがproposalプロセスを必要とするかを一貫した基準で判断できるようになります。
特に重要なのは以下の点です。

  • Windowsのシステムコール(関数・構造体・定数)を追加する場合は、Microsoftの公式ドキュメントとの1対1対応を確認するだけでCLを進められる
  • 独自のヘルパーメソッドを追加したい場合は、proposalを経由するルートが明示される
  • レビュアーによって判断がぶれることなく、コントリビューターが事前に何が必要かを把握できる

コード例

// proposalが不要な例:
// Windows API "GetIfTable2Ex" の直接的な対応物
//sys GetIfTable2Ex(level uint32, table **MibIfTable2) (errcode error) = iphlpapi.GetIfTable2Ex
// Windows構造体 "MIB_IF_TABLE2" の直接的な対応物
type MibIfTable2 struct {
    NumEntries uint32
    Table      [1]MibIfRow2
}
// proposalが必要な例:
// Windowsには存在しない独自のヘルパーメソッド
func (t *MibIfTable2) Rows() []MibIfRow2 {
    return unsafe.Slice(&t.Table[0], t.NumEntries)
}

議論のハイライト

  • 判断基準の非対称性への懸念: @aclements は GetIfTable2ExMibIfTable2 の追加にはproposalが不要なのに、それに付随する Rows() だけ必要というのは一貫性がないと指摘した。当初は「unsafe型をsafeに扱うためのヘルパーメソッドはproposal不要」という方向性を示した。
  • @alexbrainman のリスク管理観点: x/sys/windows にはバージョニングがないため、一度追加したAPIは変更不可能。過去に syscall.Filetime.Nanoseconds() の戻り値型を int64 ではなく uint64 にすべきだったという失敗例があり、慎重姿勢が根付いている背景がある。
  • 最終的な合意: @neild が提案委員会を代表して、「Windows APIとの1対1対応があるものはproposal不要、それを超えるものはproposal必要」という方針でメンテナー双方(@alexbrainman, @qmuntal)に確認し合意を得た。
  • 残された懸念と将来の展望: @aclements は「この方針がunsafeな型に対してtype-safeなメソッドを追加する動機を削いでしまうことを懸念する」と明記した上で、「trivial proposal track(軽量なproposalルート)」の整備を検討中であると述べている。
  • Windows固有の事情: Unixシステムコールとは異なり、Windowsには数千ものAPIが存在し、ツール mkwinsyscall で機械的に生成されるため、個別に安全な高レベルAPIを設計することが現実的でないという背景がある。

関連リンク