Go 1.26 小争议:`go mod init` 默认版本“降级“了?

简介: Go 1.26 工具链默认 `go mod init` 生成 `go 1.25` 模块,导致新语法(如 `new(42)`)编译报错。此举虽为兼容性考虑,却违背“最小惊讶原则”,引发开发者困惑。可手动指定 `-go=1.26` 解决。(239字)

用新工具链,却默认创建旧版本模块?开发者:这不太对吧


🎬 场景还原:一个让人困惑的瞬间

假设你刚升级到 Go 1.26,兴奋地想试试新特性:

# 1. 写个小程序cat main.go
package main
import "fmt"
func main() {
   
    fmt.Println(new(42))  # Go 1.26 新语法
}

# 2. 直接运行,没问题!
❯ go run main.go
0x4a524480c0b0  ✅

# 3. 初始化模块
❯ go mod init myapp
go: creating new go.mod: module myapp

# 4. 查看生成的 go.modcat go.mod
module myapp

go 1.25  # ❓ 等等,我用的是 1.26 啊?

# 5. 再编译,报错了!
❯ go build
./main.go:6:14: new(42) requires go1.26 or later 
(-lang was set to go1.25; check go.mod)  🚫

开发者内心OS:我装的是 1.26,为啥默认给我配 1.25?


🔍 问题核心:默认行为变了

变更前(Go 1.25 及之前)

go mod init myapp
# 生成:go 1.25  (与工具链版本一致)✅

变更后(Go 1.26)

go mod init myapp  
# 生成:go 1.25  (工具链版本 -1)❓

简单说:你用 1.26 的工具,go mod init 却默认给你创建 1.25 的模块。


🤷 为什么要这样改?

Go 团队在 #74748 中的解释:

"为了给 go directive 提供一个更好的初始值"

官方逻辑

  • Go 政策:始终支持最近 2 个大版本
  • 默认设为 当前版本-1,确保模块能在两个版本间兼容
  • 方便企业用户在多版本环境中协作

但问题来了:这个"更好",对谁更好?🤔


😕 开发者的困惑点

1. 违背"最小惊讶原则"

用户预期:用 1.26 工具链 → 默认享受 1.26 特性
实际行为:用 1.26 工具链 → 默认限制在 1.25 特性

就像买了最新款手机,开机发现默认装的是上一代系统。

2. 增加了额外步骤

想用新特性?得手动改 go.mod

module myapp

- go 1.25
+ go 1.26   # 手动升级

小项目:改一行无所谓
频繁创建模块:每次都要改,烦!

3. 理由不够充分

Issue 发起人直言:

"说这是'更好的初始值',但没解释为什么更好"


⚖️ 两派观点 PK

🔹 支持变更派(Go 团队视角)

理由 说明
🏢 企业友好 多版本团队中,默认保守版本更安全
🔙 兼容优先 确保模块能在两个支持版本中构建
🎯 可手动调整 需要新特性?改一行 go.mod 就行

🔹 反对变更派(开发者视角)

理由 说明
🧑‍💻 个人项目为主 大多数用户想用最新特性
⚡ 减少摩擦 默认行为应该"开箱即用"
🔍 预期一致 工具链版本 = 默认语言版本,一直如此

🛠️ 临时解决方案

方案 1:手动指定版本

go mod init myapp -go=1.26

方案 2:初始化后快速修改

go mod init myapp
sed -i 's/go 1.25/go 1.26/' go.mod  # Linux/Mac
# 或手动编辑 go.mod

方案 3:使用 go.work(多模块项目)

go work init
go work use .
# 在 go.work 中统一指定版本

🔮 可能的走向

目前这个 issue 处于讨论阶段,几种可能:

✅ 可能性 1:维持现状
   - 企业场景确实有需求
   - 个人用户可通过 -go 参数覆盖

✅ 可能性 2:折中方案  
   - 默认仍用工具链版本
   - 增加 --compatible 参数创建保守版本

✅ 可能性 3: revert 回原行为
   - 社区反馈强烈
   - "最小惊讶"原则优先

💡 给开发者的建议

如果你刚遇到这个问题:

# 1. 初始化时直接指定版本
go mod init myapp -go=1.26

# 2. 或者在脚本中自动化
echo "go 1.26" >> go.mod  # 追加覆盖

# 3. 关注 issue 进展
# https://github.com/golang/go/issues/77653

团队协作建议:

# 在 README 或 CONTRIBUTING 中明确:
项目要求:
  Go 版本: >= 1.26
  初始化命令: go mod init xxx -go=1.26

相关文章
|
2月前
|
JSON 安全 测试技术
别再只用 `net/http` 了!Go 高并发场景的“涡轮增压”方案:`fasthttp`
`fasthttp` 是由 Valyala 开发的高性能 HTTP 引擎,专为高吞吐、低延迟、低内存场景优化。相比 `net/http`,它快 6 倍+、零堆分配、支持百万级连接,适合 API 网关、实时服务等场景,但仅支持 HTTP/1.1。(239 字)
291 0
|
2月前
|
JSON 编解码 Go
Go 新一代网络请求resty!,比net/http好用10倍
resty 是 Go 语言高性能 HTTP 客户端,比 net/http 简洁 10 倍、比 axios 更 Go 风。零依赖、支持链式调用、自动 JSON 编解码、重试/拦截器/Mock/文件上传下载等,Go 1.18+ 可用,一行代码发起请求,大幅提升开发效率与可维护性。(239 字)
223 1
|
存储 网络协议 安全
必知的技术知识:DNS资源纪录(ResourceRecord)介绍
必知的技术知识:DNS资源纪录(ResourceRecord)介绍
|
2月前
|
前端开发 关系型数据库 MySQL
用 Go 写代码不翻车:SOLID 原则实战指南
本文用轻松幽默的方式,结合Go语言特性,详解SOLID五大设计原则在实际项目中的落地实践。通过“在线问卷系统”案例,手把手演示如何用接口、依赖注入等Go惯用法实现单一职责、开闭原则、里氏替换、接口隔离与依赖倒置,让代码更健壮、易扩展、好测试——告别改一处崩一片的噩梦!
144 6
Ansible-playbook 并发运行async、poll(学习笔记二十二)
ansible默认只会创建5个进程,所以一次任务只能同时控制5台机器执行.那如果你有大量的机器需要控制,或者你希望减少进程数,那你可以采取异步执行.ansible的模块可以把task放进后台,然后轮询它.
5277 0
|
2月前
|
Rust 安全 JavaScript
告别 `print()`!用 VS Code 调试器高效定位 Bug
本文手把手教你用VS Code调试器替代低效`print`:5步定位“越打折越贵”Bug,零代码侵入、实时查变量、支持条件断点与表达式监视。免费、高效、安全——调试本该如此简单!
323 33
|
1月前
|
人工智能 JavaScript 中间件
周下载量 600个W,这个TS版Gin框架火了?
Hono(日语“火焰”)是轻量、极速的全栈Web框架,专为边缘计算设计。支持Cloudflare Workers、Deno、Bun等多运行时,零依赖、仅14KB,内置TypeScript强类型、洋葱中间件、JSX服务端渲染及丰富官方中间件,真正“Write once, run anywhere”。
192 6