必须启用staticcheck和govet才能捕获典型并发bug:staticcheck可查sa2002/sa2003等goroutine风险,govet能检出sync.waitgroup误用、select死锁等问题;goland默认未启用staticcheck,需手动勾选并配置.golangci.yml开启相关检查项。

golangci-lint 必须启用 staticcheck 和 govet 才能捕获典型并发 Bug
GoLand 自带的默认 linter 几乎不报并发问题——govet 能查 sync.WaitGroup 用法错误、select 漏写 default 导致死锁,staticcheck 则能发现 SA2002(未等待 goroutine)、SA2003(goroutine 中使用循环变量地址)等真实风险。但 GoLand 安装后默认只开 govet 和 errcheck,staticcheck 是关闭状态。
必须手动启用:
- 进入
Settings → Go → 静态分析器,在 linter 表格中勾选staticcheck - 确保
govet已启用且未被配置文件覆盖(.golangci.yml中若写了disable-all: true,就必须显式enable它) - 不要依赖 IDE 自动识别配置文件——必须勾选「使用配置」并填入完整路径,例如
.golangci.yml(注意不是.golangci.yaml或相对路径)
配置 .golangci.yml 时要显式打开并发相关检查项
staticcheck 默认开启大部分规则,但部分并发敏感检查(如 SA2002)依赖其内部子规则启用状态;govet 的 copylocks、lostcancel、printf 等检查也需确认未被禁用。
推荐最小有效配置片段:
linters-settings:
staticcheck:
checks: ["all"] # 确保包含 SA2002/SA2003/SA2004
govet:
check-shadowing: true
check-ranges: true
check-printf: true
check-copylocks: true
check-lostcancel: true
注意:checks: ["all"] 不代表全开,而是让 staticcheck 使用其默认启用集(含并发相关),比逐条列更稳妥;若项目已有旧配置,需检查是否误加了 disable 规则如 - SA2002。
GoLand 中「Run on the fly」必须开启,否则并发问题不会实时标红
很多团队配好了 golangci-lint 却没效果,根本原因是只在 Code → Inspect Code 手动触发,而并发 Bug 往往在写完一行就埋下——比如 for range 循环里起 goroutine 传 &v,IDE 不实时标出,开发者根本意识不到。
GoLand 2026.1.1 是 2026.1 发布后的首个维护修正版本,适合已经开始体验 2026.1 新功能并希望同步补丁的开发者。它更适合用于入门项目、现有项目迁移测试和 IDE 行为验证。
正确做法:
- 进入
Settings → Tools → Go Linter - 勾选
Run on the fly(不是「Run on save」或「Run on commit」) - 确认「Severity」里把
staticcheck和govet相关问题设为Warning或更高,避免被折叠 - 重启 GoLand —— 缓存不刷新会导致新规则不加载
验证方式:写一段明显有问题的代码,例如:
for _, v := range items {
go func() {
fmt.Println(v) // 这里会标红,提示 SA2003
}()
}
多 module 项目中每个 go.mod 目录都得有独立 .golangci.yml
并发 Bug 常出现在跨 package 调用时,比如 pkg/worker 启动 goroutine,pkg/store 提供共享结构体。如果只在根目录放一个 .golangci.yml,GoLand 在打开 pkg/store 子模块时根本读不到它——因为 golangci-lint 只认与当前 go.mod 同级的配置文件。
必须做到:
- 每个含
go.mod的目录下都有.golangci.yml - 内容可完全一致,但路径不能省略;不能用符号链接或继承机制
- CI 中运行时也要显式指定路径:
golangci-lint run --config=pkg/worker/.golangci.yml ./pkg/worker/...
最容易被忽略的是:GoLand 的「Project Structure」里可能把多个 module 当成独立项目加载,此时每个 module 的 Settings → Go → 静态分析器 里的配置路径必须分别指向各自目录下的 .golangci.yml,否则只生效第一个。










