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

Go Proposal Weekly Digest

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

#79808accepted

testing: allow examples with any signature

ステータス変更: likely_accept accepted

要約

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

概要

Goのtestingパッケージにおいて、Example関数(go docが生成するドキュメント用のコード例)に任意のシグネチャ(引数・戻り値)を許可する提案です。ドキュメント目的の柔軟な例示を可能にしつつ、go testによる自動実行の対象からは除外します。

ステータス変更

likely_acceptaccepted
2026年6月25日の会議で「likely accept」となった後、7月8日の会議で追加の異論が出ないまま合意が維持され、正式にacceptedとなりました。実装作業に移る段階です。

技術的背景

現状の問題点

現在のExampleXxx関数は引数・戻り値を持たないfunc()のシグネチャに限定されており、go docにはそもそも表示されません(引数付き関数は無視されます)。そのため、以下のような自然なGoコードのパターンを例として示すことができませんでした。

  • errorを返す関数の例(os.CreateTempのようにエラーハンドリングを含む典型的なコード)
  • *testing.Tを受け取り、テストフレームワーク向けのヘルパーの使い方を示す例
  • 副作用のみを目的とし、出力を持たない使用例(例: *http.Transportを設定する関数)
    これらを表現するには、無名関数でラップして戻り値を握りつぶすなどの不自然な回避策が必要でした。

提案された解決策

  • ExampleまたはExampleXxxXxxが空か大文字始まり、既存の命名規則と同様)という名前を持つ関数であれば、引数・戻り値の有無を問わずgo docが例として表示するようになります。
  • 引数・戻り値を持つ例は、関数全体(付随するコメントを含む)がそのまま表示されますが、Playgroundでの実行可能な例(Runボタン付き)にはなりません。
  • testingパッケージはこのような例を自動実行しません。
  • 引数や戻り値を持つ例に// Output:コメントが含まれている場合は、go testがエラーとします(// Output:は自動実行される例にのみ許可されるため)。
  • 実行を伴うテストにしたい場合は、その例を呼び出す通常のTestXxx関数を別途書くことで対応します。

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

これまで表現できなかった「エラーを返す現実的なコード」や「*testing.Tを使うテストヘルパーの利用例」を、そのままの自然な形でドキュメントに残せるようになります。ライブラリの作者は、実装をコピペしてすぐ使えるような、より実践的なコード例をドキュメントに含められます。

コード例

// Before: 引数・戻り値を持つ関数はgo docが無視するため、
// 無名関数でラップしてエラーを握りつぶす必要があった
func ExampleCreateTemp() {
	if err := func() error {
		f, err := os.CreateTemp("", "example")
		if err != nil {
			return err
		}
		defer os.Remove(f.Name())
		if _, err := f.Write([]byte("content")); err != nil {
			return err
		}
		return nil
	}(); err != nil {
		log.Fatal(err)
	}
}
// After: 自然なerror戻り値のまま例として記述できる(go testでは自動実行されない)
func ExampleCreateTemp() error {
	f, err := os.CreateTemp("", "example")
	if err != nil {
		return err
	}
	defer os.Remove(f.Name()) // clean up
	if _, err := f.Write([]byte("content")); err != nil {
		return err
	}
	return nil
}
// 実行して検証したい場合は別途テストを書く
func TestExampleCreateTemp(t *testing.T) {
	if err := ExampleCreateTemp(); err != nil {
		t.Fatal(err)
	}
}

議論のハイライト

  • 競合案との比較: 本提案は*testing.Tを引数に取ることのみを許可する案(#64993)よりも一般的で、// Output:コメントとt.Logの相互作用やt.Fatal呼び出し時の扱いといった複雑な問題を回避できる点が評価されました。
  • エラーを返す例の自動失敗案(#21111)との違い: errorを返す例が非nilならテストを自動的に失敗させる案(#21111)は、他の(非Example)テスト関数がエラーを返せない現状と矛盾するため、本提案の方が好まれました。ただしianlancetaylorが指摘した通り、本提案は将来#21111を採用する余地を排除しません(// Output:コメントを伴う例のみ実行される制約が維持されるため、安全に共存可能)。
  • Playground実行可能性の犠牲: dagoodneildから、引数・戻り値を持つ例はPlaygroundで実行できなくなる(Runボタンが付かない)点への懸念が出されましたが、ianlancetaylorは「Playgroundへのコピー自体は容易であり、大きな問題ではない」と回答しました。
  • 副次的な提案の分離: *testing.Tを使う例のテスト容易性を高めるため、testing.Benchmarkに類似したtesting.Test関数(テスト結果を呼び出し元が受け取れる仕組み)の導入が議論されましたが、これは本提案とは別の独立した提案として扱うことで合意しました。
  • 承認までの経緯: 6月10日のレビューで議題入りし、6月17日にneildが提案内容を明確に再定義(引数・戻り値を持つ例は表示のみでテスト実行対象外、// Output:コメント禁止)したことで議論が収束、6月25日に「likely accept」、7月8日の会議で異論なく「accepted」となりました。

関連リンク