net/url: MustParse
要約
概要
net/urlパッケージに、URLのパース失敗時にエラーを返す代わりにパニックするurl.MustParse関数を追加するproposalです。regexp.MustCompileやnetip.MustParseAddrと同様のパターンをnet/urlにも導入します。
ステータス変更
likely_accept → accepted
2026年6月25日の会議で「likely accept」と判断された後、2026年7月8日の会議で「反対意見(consensusの変化)がなかった」として正式にacceptedとなりました。提案自体が小規模かつ既存の慣習(他パッケージのMust*系関数)との一貫性を重視するものであり、目立った異論もなかったため、スムーズに承認プロセスが進みました。
技術的背景
現状の問題点
url.Parseはエラーを返すため、コンパイル時や設計上「絶対に失敗しない」と分かっているURL文字列(定数や設定値など)を扱う場合でも、毎回エラーハンドリングの記述が必要でした。そのため多くのコードベースで、独自にMustParse相当の関数を定義する慣習が広がっていました。issue内のSourcegraph検索でも、公開リポジトリに*url.URLを返す独自のMustParse実装が数多く存在することが示されています。
提案された解決策
net/urlパッケージに以下のような関数を追加します。
func MustParse(rawURL string) *url.URL
内部ではurl.Parseを呼び出し、エラーが返された場合はパニックする、というシンプルな実装になる見込みです。regexp.MustCompile、template.Must、net/netip.MustParseAddrなど、標準ライブラリに既にある同種のAPIと同じデザインパターンを踏襲します。
これによって何ができるようになるか
グローバル変数の初期化や、設定ファイルから読み込んだ固定的なURL文字列など、「パース失敗があり得ない」と確信できる場面で、ボイラープレートなしに簡潔に*url.URLを得られるようになります。特にHTTPリバースプロキシの設定や、テストコードでのベースURL定義、CLIツールでの定数URL利用などで有用です。
コード例
// Before: 従来の書き方(各リポジトリで独自に実装されがちだった)
func mustParseURL(rawURL string) *url.URL {
u, err := url.Parse(rawURL)
if err != nil {
panic(err)
}
return u
}
var apiBase = mustParseURL("https://api.example.com/v1")
// After: 新APIを使った書き方
var apiBase = url.MustParse("https://api.example.com/v1")
議論のハイライト
- この提案は、より汎用的な「must」機構(
must.Doやmust.Getのようなジェネリック関数、あるいはビルトインのmust)を議論していた大きめのproposal(#54297)から、レビュー会議側の提案によって切り出されたものです。大きな議論が長引く一方で、小さく合意しやすい部分(url.MustParse)だけを先に決着させる狙いがありました。 - #54297側の議論では、Go 1.27で
testing.T.Must[T any](x T, err error) Tが導入可能になったことに触れつつ、「失敗しないと分かっている場合(must)」と「失敗しないことをテストする場合(assert)」は区別すべきという懸念がコアチームから示されました。テスト用の汎用Mustを安易に導入すると、アサーションのように誤用され、失敗時のメッセージ品質が下がるおそれがあるためです。 - 一方、
url.MustParseのような特定パッケージ向けのMust*関数は、この懸念とは切り離して考えられ、regexp.MustCompileなど既存の前例との一貫性(parallelism)を理由に支持されました(@earthboundkidのコメント)。 - Tailscaleの
must.Getパッケージやgithub.com/dsnet/try、github.com/ridge/mustなど、コミュニティで既に広く使われている類似実装が多数存在することも、標準化の後押しとなりました。 - 汎用的な
mustの是非については引き続き#54297で議論が継続される見込みですが、url.MustParse単体については明確な反対がなく、スムーズに承認されました。