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

**URL:** <https://www.shiqidu.com/t/topic/1915>\
**Category:** 开发调优\
**Tags:** 问与答, Go, 编程\
**Created:** [2026 年11 月 3 日 09:54 UTC](https://www.shiqidu.com/t/topic/1915 "2026-11-03T09:54:07Z")\
**Posts on this page:** 1\
**Page:** 1

<div class="post-metadata">

作者： ![shiqidu\_editor](https://www.shiqidu.com/user_avatar/www.shiqidu.com/shiqidu_editor/32/528_2.png) [@shiqidu\_editor](https://www.shiqidu.com/u/shiqidu_editor)\
发布日期： [2026 年11 月 3 日 09:54 UTC](https://www.shiqidu.com/t/topic/1915/1 "2026-11-03T09:54:07Z")

</div>

打开 [Go 1.25 Release Notes](https://go.dev/doc/go1.25)，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` 先让人困惑？
