メインコンテンツへスキップ
#80118likely_accept

go/doc: standardize deprecated comment tags

新規提案

要約

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

概要

Go には、doc comment に Deprecated: と書いて非推奨を示す慣習があります。この proposal は、その書式の定義を公式ドキュメント(go.dev/doc/comment)に一本化し、各ツールが共通で使える判定関数 doc.Deprecated を go/doc パッケージに追加するものです。

ステータス変更

(新規) → likely_accept
2026年10月29日、aclements 氏が proposal review group を代表して likely accept を宣言しました。当初の提案は判定ルールを広げる内容で、構造体フィールドの行末コメントに書いた Deprecated: も、行の途中にあるものまで認識するというものでした。レビュー会議では次の結論になり、範囲は逆に絞られています。

  • 非推奨の注記には「なぜ非推奨か」と「代わりに何を使うか」を書くべきだが、コードと同じ行のコメントにはそれを書く余地がない。
  • 標準ライブラリにある行末の Deprecated: は、実際どれも役に立たない内容だった。
    その結果、「Deprecated: は doc comment の中で、段落の先頭にある場合だけ認識する」という、今の go.dev/doc/comment の記述をそのまま正式な仕様にすることになりました。

技術的背景

現状の問題点

  • 非推奨の書式は go.dev/wiki/Deprecated と go.dev/doc/comment#deprecations の2か所に書かれており、どちらが正式な定義なのかがはっきりしません。
  • 判定ロジックは gopls(astutil.Deprecation)、staticcheck(SA1019)、pkg.go.dev などがそれぞれ独自に実装しています。そのため、ツールによって結果が違うことがあります。
  • 標準ライブラリにも Line int // The line number in the input. Deprecated: Kept for compatibility.(text/template/parse)のような行末コメントがあり、認識されるかどうかが曖昧でした。

提案された解決策

  1. go.dev/doc/comment#deprecations に「非推奨の注記は doc comment の中でのみ認識される」と明記します。「Deprecated: で始まる段落を非推奨の注記として扱う」という既存の規則は変わりません。
  2. go.dev/wiki/Deprecated は、書式については go.dev/doc/comment を参照する形にします。非推奨にするときの考え方の説明は wiki に残します。
  3. go/doc に次の API を追加します。
// Deprecated returns the deprecation notice, if any, in a doc comment.
// A deprecation notice is the text of a paragraph that starts with "Deprecated: ",
// stripped of the "Deprecated: " prefix.
// If there is no deprecation notice, it returns "", false.
//
// Doc can be [Func.Doc], [Package.Doc], [Type.Doc], or [Value.Doc].
func Deprecated(doc string) (text string, ok bool)

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

  • 静的解析ツールや linter の作者: 非推奨の判定を自前で実装しなくてよくなり、gopls や staticcheck と同じ結果が得られます。gopls の astutil.Deprecation なども、将来この関数に移行する予定です。
  • ドキュメント生成ツール: doc.Func や doc.Type の Doc フィールドを渡すだけで、非推奨の理由のテキストを取り出して強調表示できます。
  • ライブラリ作者: どう書けば確実に非推奨として扱われるかが公式に決まるため、書き方に迷わなくなります。

コード例

// Before: ツールごとに独自のヒューリスティックで判定していた
func deprecation(doc string) (string, bool) {
    for _, para := range strings.Split(doc, "\n\n") {
        if rest, ok := strings.CutPrefix(para, "Deprecated: "); ok {
            return rest, true
        }
    }
    return "", false
}
// After: 標準の判定関数を使う
pkg := doc.New(astPkg, importPath, 0)
for _, f := range pkg.Funcs {
    if msg, ok := doc.Deprecated(f.Doc); ok {
        fmt.Printf("%s is deprecated: %s\n", f.Name, msg)
    }
}

認識される書き方と、認識されない書き方は次のとおりです。

// F is a function.
//
// Deprecated: Use G instead.   // 認識される(段落の先頭にある)
func F()
type S struct {
    Line int // Deprecated: ...  // 認識されない(行末コメント)
}

議論のハイライト

  • 行末・行途中の Deprecated: は却下: 認めると、コメントを行末から前置きのコメントに移しただけで意味が変わってしまいます(neild 氏)。行末では理由を説明する余地も足りません。標準ライブラリにある該当箇所は、許可するのではなく書き直す方針になりました。
  • 段落の先頭に限定する厳格な書式を支持: seankhliao 氏と willfaught 氏は、コメント全体を読まなくても非推奨だと分かるように、段落の先頭に置くべきだと主張しました。adonovan 氏は当初「コメント中のどこにあってもよい」とする緩い定義を提案していましたが、採用されませんでした。
  • 引数の型と配置先: *ast.CommentGroup を受け取る案と ast.Node を受け取る案が比較されました。さらに「go/ast はもう API が多すぎて追加の余地がない」という意見が出ました。go/doc/comment は Markdown 風の書式を完全にパースすることが前提なので、非推奨の判定のためだけに使うのは重すぎるとされました。最終的に、doc comment が既に文字列になっている go/doc に、文字列を受け取るトップレベル関数として置くことになりました。
  • フィールドとして持たせる案は不採用: cherrymui 氏は Func や Type に Deprecation フィールドを追加する案を出しました。しかし、毎回あらかじめ解析しておく必要はなく、必要なときに呼ぶ関数で十分と判断されました。
  • 構造化アノテーションとの関係: [deprecated(...)] のような構造化されたメタデータの案も出ました。これは struct タグを型付きにする proposal #74472 などと絡む長期的な課題とされ、今回の対象からは外れています。

関連リンク