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

Go Proposal Weekly Digest

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

#12854accepted

spec: type inferred composite literals

ステータス変更: likely_accept accepted

要約

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

概要

コンポジットリテラル(構造体・スライス・マップなどの値を構築するリテラル構文)において、型名を省略できる場面を大幅に拡張するGo言語仕様変更の提案です。代入先の型がコンテキストから明確に推論できる場合に、リテラルの型指定を省略可能にします。

ステータス変更

likely_acceptaccepted
2026年4月8日のProposal Review Meetingで「likely accept」に昇格し、1週間のパブリックコメント期間を経て、2026年4月16日のMeetingにおいて「変更なし」として正式に accepted となりました。@aclements がアナウンスを行い、実装はGo 1.28を目標とすることが明記されています。なお、Go 1.27リリースサイクルには間に合わないとも述べられています。

技術的背景

現状の問題点

Go言語では現在も、コンポジットリテラルのネスト内(スライス要素や構造体フィールド)では型を省略できますが、それ以外の文脈(関数引数・return文・チャネル送信など)では型名を明示しなければなりません。これにより、特にProtocol Buffersのような深くネストした複合型を多用するコードで冗長な型名が繰り返し登場し、可読性・記述性を損なうケースがありました。

// 現在: 型名の繰り返しが発生する
type Point struct{ X, Y int }
func Draw(p Point) { ... }
Draw(Point{X: 1, Y: 2})  // 型名を明示する必要がある
// protobufのようなネストした構造
p.Options = append(p.Options, &foopb.Foo_FrotzOptions_Option{Value: 1})

提案された解決策

コンポジットリテラルの文法を変更し、型名をオプションにします。具体的には仕様の CompositeLit 定義を以下のように変更します。

// 変更前
CompositeLit = LiteralType LiteralValue .
// 変更後
CompositeLit = [ LiteralType ] UntypedLit .
UntypedLit   = "{" [ ElementList [ "," ] ] "}" .

また、代入可能性(assignability)の定義に以下の条件を追加します。
x{ <elements> } 形式の型なしコンポジットリテラルであり、同じ要素を持つ T{ <elements> } が型 T の有効なコンポジットリテラルである場合、x は型 T の変数へ代入可能」
この変更により既存の「要素型の省略(Elision of element types)」セクション全体が不要となり、仕様をさらに簡略化できます。

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

コンテキストから型が確定できる場所(代入文・return文・関数引数・チャネル送信・ポインタ型)では型名を省略でき、コードが簡潔になります。型が確定できない場所(:= による短縮宣言など)では依然としてコンパイルエラーになります。

コード例

// --- 関数呼び出し ---
// Before
Draw(Point{X: 1, Y: 2})
// After
Draw({X: 1, Y: 2})
// --- return文でのゼロ値 ---
// Before
return time.Time{}, err
// After
return {}, err
// --- チャネル送信 ---
type Result struct{ Value string; Err error }
ch := make(chan Result)
// Before
ch <- Result{Value: "ok"}
// After
ch <- {Value: "ok"}
// --- protobufのような深いネスト ---
// Before
p.Options = append(p.Options, &foopb.Foo_FrotzOptions_Option{Value: 1})
// After
p.Options = append(p.Options, {Value: 1})
// --- ポインタ型 ---
var tree *Tree = {}   // &Tree{} と同等
// --- エラーになるケース(型が推論できない) ---
a := {1, 2, 3}  // コンパイルエラー: 左辺に型指定がない

議論のハイライト

  • 長期間の懸案: この提案は2015年に作成され、10年以上にわたって議論されてきた。当初Goチームは可読性への懸念と、ジェネリクス実装優先の方針から先送りにしていた。ジェネリクスが完成した後に改めて検討が本格化した。
  • Go 1リリース前に一度実装・撤回: @adg によると、Go 1のリリース前に類似機能を一度実装したが「全体的にコードの可読性を低下させる」という理由で撤回した経緯がある。今回はGo生態系の実態(特にprotobuf利用)を踏まえ再評価された。
  • 「型なしリテラル」という呼称の問題: @minux@ianlancetaylor は「untyped」という用語がGoの既存概念(untyped constants)と混同されると指摘。実態は「型推論によって型が確定できる場合の型名省略」であり、本質的には既存の型省略ルールの拡張。
  • 可読性vs簡潔性のトレードオフ: コアチームの @aclements は、TypeScriptとVS Codeの関係を例に「IDE/gopls のサポート(型ヒント表示)で可読性の懸念を実用的に解消できる」と判断。gofmt -s を拡張して型を積極的に削除するような変更は行わない方針。
  • スコープの明確化: 型が推論できない場合(:= の右辺、interface{} 型変数への代入など)は従来通りコンパイルエラーになることが確認され、安全な変更であることが確認された。

関連リンク