errcheck默认不检查类型断言和_赋值,需在.golangci.yml中启用check-type-assertions: true和check-blank: true;同时须配置run: tests: true、issues-exit-code: 1,并协调unused检查以避免漏报。

errcheck 默认不检查类型断言和 _ 赋值,容易漏掉真实错误
默认情况下 errcheck 只检查函数调用返回的 error 是否被忽略,对 a := b.(MyStruct) 这类类型断言失败、或 _, err := strconv.Atoi(s) 这种显式丢弃 error 的写法完全沉默——而这两种场景在微服务中极易引发 panic 或静默逻辑跳过。
必须在 .golangci.yml 中显式开启两项关键配置:
-
check-type-assertions: true:让 errcheck 报告所有未检查的类型断言结果(即缺少第二个 bool 返回值) -
check-blank: true:禁止用_接收 error;若真要忽略,必须改用_ = err+ 注释说明(配合 revive 规则可进一步约束)
示例错误代码会被捕获:
val, _ := json.Marshal(data) // check-blank: true → 报错 obj := someInterface.(MyType) // check-type-assertions: true → 报错,应写成 obj, ok := someInterface.(MyType)
errcheck 和 unused 冲突:未使用的 error 变量可能绕过检查
当一个函数返回 error,但你把它赋给了一个后续完全没用的变量(比如 err := doSomething() 之后再没引用 err),unused linter 会先报“变量未使用”,而 errcheck 根本不会触发——因为变量已声明,它不认为 error 被“忽略”了。
这会造成虚假安全感。解决方式只有两个:
- 在
.golangci.yml中确保unused和errcheck同时启用,且unused不禁用 error 类型变量检测(默认开启) - 把 error 检查写成一行:
if err := doSomething(); err != nil { return err }——这样既通过 errcheck,又避免 unused 报警
测试文件里 errcheck 失效?别忘了 run.tests 配置
默认 golangci-lint run 不检查测试文件(*_test.go),所以 sql.Open(...) 后直接用 db.Ping() 却不检查 error,在 test 文件里永远不会被 errcheck 发现。
必须在配置中显式打开:
run: tests: true
同时注意:如果测试中用了 mock 或临时资源(如 tempfile),某些 error 确实可安全忽略,这时用 issues.exclude-rules 精准跳过更稳妥,例如:
issues:
exclude-rules:
- path: "_test\.go"
linters:
- errcheck
text: "os.Create.*temp"
CI 中 errcheck 失效的最常见原因:没设 issues-exit-code
golangci-lint run 默认即使发现 100 个 errcheck 问题,退出码仍是 0,CI 就当成功——这是最隐蔽也最致命的配置遗漏。
必须加这一行:
run: issues-exit-code: 1
否则,PR 里一堆 _, err := http.Get(...) 直接合入主干,没人知道。
真正难的不是写规则,而是让每条规则在每个环节(IDE、pre-commit、CI)都稳定生效;漏掉任意一环,errcheck 就只是个摆设。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











