#54297hold
must: Do
ステータス変更: discussions hold
要約
AIによる要約であり、誤りを含む場合があります。
概要
proposal #54297は、エラーが発生した場合にpanicする汎用ヘルパー関数must.Doを標準ライブラリに追加する提案です。元々はurl.MustParseの追加提案でしたが、より汎用的なmustパッケージへと議論が発展しました。
ステータス変更
discussions → hold
2026年1月28日の提案レビュー会議で、この提案は一旦保留(hold)となりました。保留の理由は、#77273(ジェネリックメソッドの提案)の解決を待つためです。ジェネリックメソッドが実装されれば、func (*testing.T) Must[T any](v T, err error) Tのような、より便利なAPIが実現可能になります。
技術的背景
現状の問題点
Go言語では、エラーを返す関数を呼び出す際、通常は明示的なエラーチェックが必要です。しかし、初期化コードやグローバル変数の設定など、引数が定数で確実に成功することが分かっている場面では、このボイラープレートコードが冗長になります。
// Before: 従来の書き方(冗長なコード)
import "net/url"
var baseURL *url.URL
func init() {
u, err := url.Parse("http://example.com/")
if err != nil {
panic(err)
}
baseURL = u
}
// または
var baseURL = func() *url.URL {
u, err := url.Parse("http://example.com/")
if err != nil {
panic(err)
}
return u
}()
現在の標準ライブラリには、このパターンを簡潔に書くためのregexp.MustCompileやtemplate.Mustなどの関数が個別に存在しますが、汎用的な解決策はありません。
提案された解決策
Tailscale社が開発したmust.Getパターンをベースに、以下のようなシグネチャの汎用関数を標準ライブラリに追加する案が議論されました:
// 値を返す関数用
func Get[T any](v T, err error) T {
if err != nil {
panic(err)
}
return v
}
// 2つの値を返す関数用
func Get2[T any, U any](v1 T, v2 U, err error) (T, U) {
if err != nil {
panic(err)
}
return v1, v2
}
// エラーのみを返す関数用
func Do(err error) {
if err != nil {
panic(err)
}
}
これによって何ができるようになるか
グローバル変数の初期化やテストコードにおいて、定数引数で呼び出される関数のエラーハンドリングが大幅に簡潔になります。
コード例
// After: 新APIを使った書き方
import "errors" // または "must" パッケージ
var baseURL = errors.Must(url.Parse("http://example.com/"))
// テストコードでの使用例
func TestSomething(t *testing.T) {
data := errors.Must(json.Marshal(testStruct))
loc := errors.Must(time.LoadLocation("America/New_York"))
// ...
}
// bytes.Bufferなど、実質的に失敗しない操作での使用
func packData() []byte {
var buf bytes.Buffer
errors.Must(0, buf.WriteByte('x'))
return buf.Bytes()
}
議論のハイライト
- パッケージ名の議論:
mustという新パッケージを作るか、既存のerrorsパッケージに入れるかで意見が分かれました。一つの関数のためだけに新パッケージを作ることへの懸念がありました。 must.Doの是非:must.Do(err)はエラーハンドリングのショートカットとして悪用される可能性があり、特にmain関数での使用が懸念されました。一方で、bytes.Bufferへの書き込みなど、実質的に失敗しない操作には有用との意見もありました。- 使用実態の調査:
- Tailscaleの200KLoC規模のコードベースでは、1,265箇所で使用され、最多は
json.Marshal(18%)でした - 定数引数のみでの使用は極めて少なく、ほとんどが動的な引数での使用でした
- テストコードでの使用が全体の約2/3を占めていました
- Tailscaleの200KLoC規模のコードベースでは、1,265箇所で使用され、最多は
- testing.Mustの可能性: テスト用の
testing.Must(t, err)またはtesting.T.Must[T any](v T, err error) Tの追加も議論されましたが、現在の型システムではtesting.T.Mustの実装が困難です。ジェネリックメソッドが実装されれば、この問題は解決します。 - vet検査による制限: 定数引数のみでの使用を強制する
vet検査を追加する案も提案されましたが、実際の使用パターンとは合致しないことが判明しました。 url.MustParseへの原点回帰: 議論の結果、元々の提案だったurl.MustParseだけを追加する案も再検討されましたが、実際の使用頻度が低いことが分かりました。