Go 1.25 发布说明里语言没改,日常会撞上的是 go.mod ignore 和几条新 vet

打开 Go 1.25 Release Notes,Introduction 写得很直:2025 年 8 月发布,距 1.24 约半年,改动主要在工具链、运行时和标准库,并继续守 Go 1 兼容性承诺,绝大多数程序应能照旧编译运行。Changes to the language 一节更干脆:没有影响 Go 程序的语言变更(规范文案里去掉了 core types 的说法,那是文档层调整)。本地 go version 已经跳到 1.25 的人,如果第一反应是翻语法有没有新花样,这一节基本可以合上。

对日常开发更有感的,反而是命令和 vet 多出来的几处行为。

go.mod 的 ignore

新加了 go.mod 的 ignore 指令,用来标明 go 命令应当忽略的目录。匹配到的目录及其子目录,在 all、./... 这类包模式匹配时会被跳过,但仍然会进 module zip。单体仓库里塞了生成物、第三方源码快照、或根本不是 Go 包的大目录时,以前常靠手工剔路径。现在可以在 go.mod 里写明忽略规则,减少 go test ./... 误扫。

有个边界要记住:忽略的是模式匹配,不是「从模块里物理删除」。做发布、下 zip 的流程如果假设某些目录不存在,和 ignore 的语义并不相同。

几条新 vet,以及 -asan

go vet 新增分析器,发布说明点名了:

  • waitgroup:报告放错位置的 sync.WaitGroup.Add 调用
  • hostport:报告用 fmt.Sprintf("%s:%d", host, port) 拼 net.Dial 地址的写法,在 IPv6 下会出问题,建议改用 net.JoinHostPort

升完工具链之后,CI 里原本干净的 go vet ./... 突然红,优先看是不是这两类新规则被扫到,而不是先怀疑 vet 坏了。把 Add 丢进 goroutine 里、在外层 Wait 之前才加计数,是 waitgroup 最常盯到的写法之一。hostport 则多半出现在旧的「字符串拼 host:port」工具函数里。

go build -asan 默认会在进程退出时做泄漏检测:若 C 分配的内存既没释放、又没被其它 C/Go 分配的内存引用,会报错。需要关掉时,运行程序前设 ASAN_OPTIONS=detect_leaks=0。混了 cgo、或测试里故意留了原生泄漏的仓库,升完第一次全量测试可能会被这项默认行为砸到。

其它顺手能碰到的还有:go doc -http 会起文档服务并打开浏览器。go version -m -json 能把二进制里的 BuildInfo 打成 JSON。更新 go.mod / go.work 里的 go 行时,不再顺手加一条指向当前命令版本的 toolchain 行。发行版预置的工具二进制也变少了,不参与 build/test 的工具改由 go tool 按需构建。

容器里的 GOMAXPROCS

默认 GOMAXPROCS 行为变了。Linux 上若进程落在带 CPU bandwidth limit 的 cgroup 里,而该限制低于逻辑 CPU 数,默认会取较低的那个。在 Kubernetes 一类环境里,这通常对应 CPU limit,而不是 request。所有操作系统上,逻辑 CPU 数或 cgroup 限制变化时,运行时还会周期性更新 GOMAXPROCS。手工设了 GOMAXPROCS 环境变量或调用过 runtime.GOMAXPROCS,上述行为会自动关掉。也可以用 GODEBUG 的 containermaxprocs=0、updatemaxprocs=0 分别关掉。

在限额很小的容器里跑旧二进制,和新的 1.25 默认值比,能吃到的 P 数可能不一样。性能对比或排障时,先看自己有没有显式钉死 GOMAXPROCS,再谈版本差异。需要恢复成「按运行时默认值来」时,发布说明提到了 runtime.SetDefaultGOMAXPROCS。

兼容性上多留一眼的点

发布说明里修了一个 1.21 引入的编译器问题:有些「先用 os.Open 的结果、后判断 error」的错误写法,在 1.21–1.24 会错误地跑过去,1.25 起会按规范在 nil 指针处 panic。代码如果真有这种顺序,应把非 nil 的 error 检查挪到使用结果之前,而不是怪运行时突然变严。

平台侧也有硬门槛:macOS 需要 12 Monterey 或更新。windows/arm(32 位)仍带着,但说明里写明 1.25 是包含这个破损端口的最后一版,1.26 会移除。实验性的东西(如 GOEXPERIMENT=greenteagc、GOEXPERIMENT=jsonv2)发布说明着墨不少,但默认不开就不影响现有构建。先把 ignore、新 vet、-asan 默认泄漏检测、容器 GOMAXPROCS 这几项写进升级清单,通常就够应付日常仓库。

你们升到 1.25 以后,是 vet 先红,还是容器里的 GOMAXPROCS 先让人困惑?