#76163likely_accept
policy for removing GODEBUG flags
ステータス変更: active likely_accept
要約
AIによる要約であり、誤りを含む場合があります。
概要
GODEBUG 環境変数のフラグ(設定)を安全かつ計画的に廃止・削除するための公式ポリシーを策定するproposalです。13年間にわたって蓄積された技術的負債を解消し、GODEBUGフラグのライフサイクル管理を体系化することを目的としています。
ステータス変更
active → likely_accept
2026年5月20日のProposal Review Meetingにおいて、@aclementsが「likely accept」と判定しました。提案者の@griesemeが長期にわたる議論を経て提案を整理し、Go 1.27に向けたポリシーと実装を固めた段階で、コアチームの合意が得られたためです。runtime.SetGODEBUG / GetGODEBUG の導入については、より詳細な検討が必要なため Go 1.28 での別提案に分割することとなり、Go 1.27 向けにスコープを絞ったことが承認判定を後押しした可能性があります。
技術的背景
現状の問題点
Go 1(2012年)以降、Go チームはセキュリティや仕様変更に伴う振る舞いの変更をスムーズに移行させるため、GODEBUG 環境変数による設定フラグを導入してきました。例えば Go 1.21 の panicnil フラグは、panic(nil) の動作を以前に戻すためのものです。
しかし13年間の運用でフラグが増殖し、以下の問題が生じています。
- メンテナンス負荷の増大: フラグごとに旧来の動作分岐が存在し続ける
- テストの複雑化: 動作の分岐点が多く、網羅的なテストが困難
- 一貫性のなさ: 削除予定日のあるフラグ、恒久フラグ、曖昧な位置づけのフラグが混在し、統一的な管理ポリシーが存在しない
提案された解決策
フラグをカテゴリ別に分類し、各カテゴリに対応した廃止・削除プロセスを定めます。
既存フラグの削除プロセス(2ステップ):
- 恒久フラグ、または削除予定日のないフラグを削除したい場合: 削除予定日を記載したproposalを提出(導入から2年以上かつ半年以上先)。承認されたらステップ2へ。承認されなければ恒久フラグとしてマーク。
- 削除予定日が確定したフラグ: 削除予定リリースの直前リリースで「削除予定(slated for removal)」とアナウンスし、リリースノートで告知。反発がなければ次のリリースで削除。強い反発があれば1サイクル(半年)延期して繰り返す。
新規フラグへのポリシー:
新たに導入するGODEBUGフラグは、「恒久フラグ」か「導入から2年(4リリースサイクル)以上先の削除予定日付き」のいずれかとして明示することを義務付けます。
実装上の変更:
- 削除予定とマークされた設定に非デフォルト値を指定した場合、
go vetが静的チェックで警告を報告(言語バージョンではなくツールチェーンバージョンに依存) - 削除済みの設定に非デフォルト値を設定した場合、ビルドエラーとなる
- 起動時(スタートアップ時)に
GODEBUG環境変数で削除済みフラグが非最終デフォルト値に設定されていればパニックを発生させる internal/godebugsパッケージに「削除予定テーブル」を追加(既存のRemovedテーブルと同様)- 名前の再利用防止のため、
AllテーブルおよびRemovedテーブルで全フラグ名を保持し続ける
これによって何ができるようになるか
このポリシーにより、GODEBUGフラグのライフサイクル全体が透明かつ予測可能になります。
開発者にとっての具体的なメリット:
- マイグレーション猶予期間の保証: 削除の半年前にアナウンスされるため、対応する時間が確保される
- ツールによる早期検出:
go vetが削除予定のフラグ使用を検知し、削除前に修正できる - エコシステムの安定性向上: フラグ名の再利用禁止により、意図しない動作変更を防止できる
コード例
// Before: 削除予定フラグを従来どおり設定(Go 1.27以降は go vet が警告)
//go:debug gotypesalias=0
// After: 削除予定のフラグを使わず新しい動作に移行する
// (gotypesalias は Go 1.27 で削除予定。デフォルト値=1 の場合はそのまま設定可)
//go:debug gotypesalias=1 // デフォルト値であれば引き続き許容(ビルドエラーにならない)
// 削除後: 非デフォルト値の指定はビルドエラー
//go:debug gotypesalias=0 // ビルドエラー: 削除済みの設定に非デフォルト値
// 削除済みフラグをスタートアップ時に環境変数で設定 → パニック
// GODEBUG=gotypesalias=0 ./myapp // パニック発生
// 削除済みフラグをデフォルト値で設定 → 許容(ただし go vet は警告)
// GODEBUG=gotypesalias=1 ./myapp // 許容(無視される)
議論のハイライト
- GODEBUGの言語バージョン非依存性: 削除済みGODEBUGへの制約は言語バージョン(go.modのgoディレクティブ)ではなくツールチェーンのバージョンに依存する。これはGoランタイムが削除済みフラグの非デフォルト値を技術的に実現できない(旧動作を実装しない)ためであり、
go vetの静的チェックも同様の制約を持つ(@aclementsが指摘)。 os.Setenv("GODEBUG", ...)の扱い: 動的なGODEBUG変更について、削除済みフラグをSetenvで設定した場合にパニックさせるかどうかが長く議論された。最終的にSetenvの振る舞いは変更せず、スタートアップ時の環境変数処理でのみパニックを発生させることとした。runtime.SetGODEBUG/GetGODEBUGの導入については Go 1.28 向けの別提案に延期。- 「deprecated」という用語の回避: @FiloSottileが「GoではAPIの
Deprecatedは削除を意味しない」という文化があるため、GODEBUGの廃止予告にDeprecatedという語を使うと混乱を招くと指摘。最終案では「slated for removal(削除予定)」という表現に改められた。 - デフォルト値での使用は許容: 削除済みフラグでも最終デフォルト値(新しい動作を意味する値)に設定する場合はエラーにしない。これにより、すでに新しい動作に依存しているコードが削除フラグを明示的に設定していても、ビルドが壊れないよう配慮している(関連: #79422)。
- 既存フラグへの即時適用: Go 1.27でいくつかのフラグ(
gotypesalias、asynctimerchanなど)が削除予定であり、このポリシーはこれらの削除にも適用される。ただし今回の削除は既存プロセスで行われており、ポリシーが正式に適用されるのは承認後から。