编程 Go 1.27 升级笔记:编译能过,先响的是 vet、gofmt 和 go.mod diff

2026-11-11 21:06:37

Go 1.27 升级笔记:编译能过,先响的是 vet、gofmt 和 go.mod diff

Go 1.27 这批改动大多落在工具链行为上,语言本身没有变动。升级后最先卡住的通常不是 go build 失败,而是 CI 里突然多出来的 vet 报告、gofmt 的空白 diff,以及 go mod tidy 改写的 go.mod。

  • Release notes:https://go.dev/doc/go1.27
  • 仓库:https://github.com/golang/go

go test 默认调用 stdversion

go test 现在默认运行 stdversion vet 检查。它报告的是:文件中使用了比「该文件当前生效的 Go 版本」更新的标准库符号。生效版本由 go.mod 的 go 指令和该文件上的 build tag 共同决定。老模块如果一直没抬 go 行,换上新工具链后这项检查就可能开始报。

// 文件带 //go:build go1.26,go.mod 也停在 go 1.26
// 但代码里用了 go1.27 才加的标准库符号 —— stdversion 会报出来

go mod tidy 合并重复 require 块

对 go.mod 中声明 go 1.27 或更高版本的模块,go mod tidy 会自动合并重复的 require 块,保证文件里最多两个块:直接依赖一个,间接依赖一个。依附在依赖上的注释块会保留;如果一个注释块同时关联直接依赖和间接依赖(混合),合并后会挂到新的直接依赖块上。此前手工编辑、未解决的 Git 合并冲突、历史升级都会留下多个互不相连的 require 块,tidy 要么原样留着,要么又造出新的;现在强制两块布局。升级后 go.mod 出现 diff 属于预期结果。

gofmt 的列对齐判定

gofmt(以及 go/format)判断列对齐的逻辑修了。旧逻辑让 gofmt 的行为在不同 CPU 架构上略有差异,新逻辑会改变少量文件的对齐决定。用 Go 1.27 的 gofmt 重新格式化以前格式化过的代码,可能产生少量空白变化。

go tool trace 的 -http 只绑 localhost

go tool trace 的 -http 只传端口时(如 -http=:6060),现在把监听地址限制在 localhost,与 go tool pprof 的 -http 行为一致。要在所有地址上监听,得把地址显式写出来。

# 仅 localhost
go tool trace -http=:6060 trace.out

# 所有地址
go tool trace -http=0.0.0.0:6060 trace.out

vet printf 新增 %w 报告

printf 分析器现在会报告 fmt.Errorf("...: %w", p) 这类调用:%w 的操作数 p 类型是 *E,而 E 本身实现了 error。这样包一层指针通常是潜伏 bug,会让按具体错误类型判断的操作假失败,比如类型断言或 errors.Is。

type E struct{ msg string }
func (e *E) Error() string { return e.msg }

var p *E = &E{"boom"}
err := fmt.Errorf("wrap: %w", p) // vet: %w 的操作数是 *E,而 E 实现了 error

GODEBUG 里已移除的开关

go 命令现在会检查那些「支持已移除」的 GODEBUG 设置(例如 asynctimerchan),位置包括 go.mod 的 godebug 条目和源码里的 //go:debug 注释。如果写的是移除前确立的最终默认值,命令接受;如果写的是旧值,go 命令直接失败。

// go.mod
godebug (
	asynctimerchan=1 // 旧值:go 命令直接失败
)
//go:debug asynctimerchan=1
package main

落地顺序

  1. 只换工具链,不改代码,先跑构建和测试,确认失败与升级无关。
  2. 更新 go 行,再跑 go mod tidy,把 go.mod 的合并 diff 一次性看掉。
  3. 单独看 gofmt diff,避免和逻辑改动混在一个提交里。
  4. 最后处理 vet 新增报告:stdversion 与 printf 的 %w 两类。
# 1. 只换工具链
go version          # go1.27.x
go build ./...
go test ./...

# 2. 抬 go 行并整理依赖
go mod edit -go=1.27
go mod tidy

# 3. 格式化差异
gofmt -l .
gofmt -d ./some/pkg

# 4. 新增 vet 报告
go vet ./...

另外,go test -json 的 "Action":"output" 行多了可选的 OutputType 字段,当前取值包括 error、error-continue、frame;若有脚本在解析测试输出,需要留意这个新字段。

复制全文 生成海报 Go 工具链 CI 升级

推荐文章

程序员茄子在线接单