苦等11年,Go 终于决定通过复合字面量的提案了,开发者直呼yyds。
2015年10月6日,一个普通的周二。
一位名叫 neild 的 Go 贡献者在 GitHub 上提交了一个看似不起眼的关于复合字面量的提案,标题很克制:“spec: type inferred composite literals”。

提案的意思就是希望让Go代码更加简单:能不能让我少写几个字?
比如这样:
// 以前
var x []string = []string{"a", "b", "c"}
// 以后(如果提案通过)
var x []string = {"a", "b", "c"}
看起来只是省了几个字符,对吧?
但就是这个"小想法",在 Go 社区里吵了整整 11 年。
直到 2026 年 4 月 15 日,提案状态终于从 “Likely Accept” 变成了 “Accepted” 🎉

一场"删字符"引发的哲学战争
你可能会想:不就是少写几个类型名吗?至于吵 11 年?
至于。
因为这个问题背后,藏着 Go 语言最核心的设计哲学冲突:显式优于隐式,到底应该坚持到什么程度?
让我讲个真实故事。
三年前,我带一个新人写 Go。他兴奋地用上了各种"简洁写法":类型推断、省略返回值变量名、匿名结构体……代码确实短了 30%。但两周后,他离职了。接手代码的我,花了整整两天才搞明白某个函数到底返回的是什么类型。
那一刻我突然理解了为什么 Go 团队当初那么"固执":
“宁可多写两行,也要让三个月后的自己能看懂。”
为什么这个提案值得吵 11 年?
让我用三个场景说明,为什么有人愿意为"少写几个字"坚持这么久。
场景一:函数参数的"结构体包装"模式
很多 Go 开发者都遇到过这种写法:
// 参数太多?包成结构体!
type Config struct {
Host string
Port int
Timeout time.Duration
}
func Connect(cfg Config) { ... }
// 调用时
Connect(Config{
Host: "localhost",
Port: 8080,
Timeout: 30 * time.Second,
})
但如果能省略类型呢?
func Connect(cfg struct {
Host string
Port int
Timeout time.Duration
}) { ... }
Connect({
Host: "localhost",
Port: 8080,
Timeout: 30 * time.Second,
})
是不是清爽多了?特别是当这个结构体只在这个函数里使用时,单独定义一个类型反而增加了认知负担。
场景二:Channel 通信的"轻量元组"
这是我最想要的特性:
ch := make(chan struct {
value string
err error
})
// 以前
ch <- struct {
value string
err error
}{value: "result", err: nil}
// 以后(梦想中)
ch <- {value: "result", err: nil}
看到没?这本质上是在用匿名结构体模拟"元组"。虽然没有真正的 tuple 语法糖,但这种写法已经能让代码优雅不少。
场景三:Protobuf 的"嵌套地狱"
如果你写过 gRPC 服务,一定懂这种痛:
req := &mypb.Request{
Options: &mypb.Request_Options{
Filter: &mypb.Request_Options_Filter{
Conditions: []*mypb.Condition{
{Field: "age", Op: ">", Value: 18},
},
},
},
}
如果每一层都能省略类型……嗯,我不敢想,怕笑出声。
反对派的声音:可读性真的不重要吗?
当然不是。
提案的反对者(包括 Go 核心团队成员)提出了几个非常有力的观点:
第一,"省略类型"会让代码失去"自文档"特性。
当你看到 []string{"a", "b"},你立刻知道这是一个字符串切片。但看到 {"a", "b"},你需要往上找变量声明,或者依赖编辑器的类型提示。
第二,歧义问题。
const A = "A"
var x struct{ A int }
var m map[string]int
x = {A: 1} // 这是给结构体字段赋值?
m = {A: 1} // 还是给 map 的键赋值?
虽然提案明确说 {A: 1} 会根据目标类型解析(A 是变量名而非字符串),但这种"上下文依赖"本身就增加了理解成本。
第三,工具链的挑战。
Go 的一大优势是"开箱即用"的工具体验。但如果类型可以省略,gopls、gofmt、staticcheck 等工具都需要重新思考:
- 代码补全时,要不要自动补上被省略的类型?
- 格式化时,要不要"智能"地恢复某些类型?
- 重构时,如何保证省略类型的代码不会"静默出错"?
这让我想起海德格尔的警告:“技术的本质不在于技术本身。” 当我们讨论"要不要省略类型"时,本质上是在讨论:我们希望开发者与代码建立什么样的关系?
作为一个写过几十万行 Go 的开发者,我对这个问题的态度经历了三个阶段:
阶段一(新手期):“能少写就少写!简洁即正义!”
阶段二(踩坑期):“等等,这代码怎么看不懂了?是谁写的?哦,是我自己……”
阶段三(成熟期):“简洁很重要,但清晰更重要。关键是要有’可逆的简洁’。”
什么叫"可逆的简洁"?
就是:你可以选择省略类型让代码变短,但工具能一键恢复类型让代码变清晰。就像拍照时的"人像模式"——背景虚化是为了突出主体,但原图始终在那里,需要时随时能调出来。
这其实也是 Go 团队最终接受提案的关键前提:
“我们不希望鼓励人们在不该省略的时候省略类型,但我们也不知道如何自动判断’该不该’。所以,把选择权交给开发者,把’恢复类型’的能力交给工具。”
回到开头:为什么吵了 11 年,现在终于接受了?
我觉得有三个原因:
第一,生态成熟了。
2015 年,Go 的工具链还很基础。但现在,gopls 已经能提供强大的类型提示、跳转、重构能力。即使你省略了类型,编辑器也能"无感"地帮你补全上下文。
第二,使用场景更清晰了。
11 年的社区实践让大家明白:哪些场景省略类型真的能提升可读性(比如轻量结构体参数),哪些场景会适得其反(比如复杂嵌套的初始化)。经验比理论更有说服力。
第三,“接受"不等于"鼓励”。
提案通过后的评论很有意思:
“我们不会修改 gofmt 来自动移除类型,因为我们不知道什么时候该移除。”
这其实是一种很"Go"的智慧:提供能力,但不强制使用;相信开发者,但不纵容懒惰。
写到这里,我忍不住想:
为什么一个简单的"省略类型"功能,需要 11 年才能落地?
因为语言设计本质上是一个"熵减"过程。每增加一个特性,语言的复杂度就增加一分。而复杂度的代价,会由每一个使用者承担。
罗素在《西方哲学史》里说过:“参差多态乃是幸福本源。” 但编程语言不一样——一致性才是效率本源。
当你允许 {A: 1} 既可以赋值给 struct{A int},也可以赋值给 map[string]int(A 是变量),你就引入了"上下文依赖"。而上下文依赖,是认知负担的源头。
所以,11 年的争论,不是在争"能不能少打字",而是在争:我们愿意为简洁付出多少认知成本?
写在最后
苏格拉底说:“认识你自己。”
我觉得这句话送给编程语言设计者也合适:认识你的用户。
新手需要显式,因为他们在建立心智模型;
专家需要简洁,因为他们已经在脑中构建了类型图谱;
团队需要一致,因为协作的本质是降低沟通成本。
Go团队表示:按照目前的开发周期,这项功能不太可能进入 Go 1.27,我们的目标是 Go 1.28。尽管编译器层面的实现其实相当简单,但这项改动会对工具链产生重大影响,我们需要仔细考虑在 gopls 中的兼容与体验方案。
不过也要心急同时又有趣的网友和Go团队battle表示,既然 gopls 是独立的发布周期,而且这个语言特性的实现又 “相当简单”…… 那我们能不能想个办法把它放进 Go 1.27 里?工具链可以按自己的节奏慢慢追赶,但至少让我们这些开发者能早点玩上这个超棒的新特性嘛。
因为语言和工具应该是解耦的关系,语言特性该先发,工具后续跟上,而不是反过来让工具决定语言什么时候能发布。
但是Go团队表示坚决反对,新版 IDE ,比如Goland如果无法适配最新正式版 Go 语言,会带来极差的用户体验。而且针对 Go 1.27 里其他的语言变更,我们本身还有不少工具适配工作没做完,所以只能委屈人类,大家只能再老老实实手写类型名,继续熬半年。
还有热心的网友希望在有了这个功能之后,可以给fmt加一个功能,让它自动把省略的类型补回来。即使在在 AI 时代,可读性远比少敲几下键盘重要得多。
在我看来,这种关于简洁性和可读性,其实任何一门发展的语言都会遇到,Go 允许简化书写,不代表可以把关键类型信息全部隐去。类型本身是代码的语义骨架,是给阅读者、给工具、给后续维护者的「语义路标」。全都省略,看似代码更短,实则砍掉了必要的信息支撑,从 “简洁” 滑向 “晦涩”。
维特根斯坦在《逻辑哲学论》早就提醒我们:语言的模糊,必然带来思想的混乱,一切伟大的表达,都以直白易懂为最高准则;绕弯子与刻意隐晦,都是平庸的掩饰。。
这很像人生:年轻时我们追求"做减法",以为简洁就是高级;成熟后我们明白,真正的优雅,是在复杂中找到平衡。
所以,当你在未来的 Go 代码里看到 var x []string = {"a", "b"} 时,不必惊讶。
那不只是少写了几个字符,那是一个语言、一群开发者、11 年时间,共同找到的"刚刚好"。
- 点赞
- 收藏
- 关注作者
评论(0)