golangci-lint配置生效需满足三点:文件名必须为.golangci.yml且与go.mod同级;YAML顶层字段(run、linters等)顶格平级、缩进严格;启用staticcheck、unused等关键linter,禁用golint。

配置文件名和位置必须严格匹配
golangci-lint 不会自动识别 .golangci.yaml、golangci.yml 或 .golangci.yml 放在 src/ 下——只有 .golangci.yml(注意是点开头 + yml 小写)且与 go.mod 同级时才生效。多 module 项目中,每个 module 目录都得有自己的一份,根目录的配置不会向下继承。
常见错误现象:golangci-lint run 安静退出、零输出,但 CI 报一堆 SA1019 或 unused;本地改了配置却没反应。
- 检查当前路径下是否存在
go.mod,再确认.golangci.yml是否与它同级 - 用
ls -a | grep golangci确认文件名拼写(不是.yaml,不是golangci.yml) - CI 脚本中必须显式加
--config=.golangci.yml,不能依赖自动发现
YAML 语法错误导致配置静默失效
缩进错位、冒号后少空格、用了 Tab 替代空格、顶层字段嵌套错层——这些都会让 golangci-lint 忽略整个配置文件,退回到默认启用集(仅 govet、errcheck 等约 10 个),而不会报错提示。
典型误配:linters-settings 写成 linters 的子项,或把 run 和 linters 缩进到同一级但实际缩进多了一格。
立即学习“go语言免费学习笔记(深入)”;
- 用
yamllint .golangci.yml验证基础语法(需提前安装) - 所有顶层字段(
run、linters、linters-settings、output)必须顶格,且彼此平级 -
linters.enable是列表,每项前用-+ 空格,不能漏空格或换行错位 - 避免复制网上示例时带入不可见字符(如全角空格、Zero Width Space)
linter 启用逻辑不满足真实需求
装完 golangci-lint ≠ 自动查出泛型误用、弃用 API、恒真判断等关键问题。像 staticcheck、unused、gosimple 这些真正暴露深层缺陷的 linter,默认是关闭的;golint 则早已归档,继续启用只会增加误报和维护负担。
常见错误:只启用了 govet 和 errcheck,结果上线后才发现 time.Now().Unix() > 0 这类 SA4006 问题一直没被拦截。
- 最小有效组合建议直接写死:
enable: [govet, errcheck, staticcheck, unused, gosimple] - 显式禁用过时工具:
disable: ["golint"](不是golint,大小写敏感) -
staticcheck若需更细粒度控制(如关掉某条 SA 规则),须在linters-settings.staticcheck下配checks,而非靠disable全局关掉 - 别碰
dupl(重复代码)和lll(行长),它们阈值难调、易误报,不适合卡 CI
CI 与本地行为不一致的根源排查
CI 报错而本地不报,90% 不是代码问题,而是环境漂移:GO111MODULE 状态、Go 版本、模块解析路径、甚至 GOPATH 设置不一致,都会导致 go list -deps 失败,进而让部分 linter(如 staticcheck)跳过分析。
典型表现:golangci-lint run --config=.golangci.yml 在 CI 中只跑了几秒就退出,且无任何 issue 输出。
- CI 脚本开头统一加:
export GO111MODULE=on,并确认 Go 版本与本地一致(如1.21) - 在 CI 中加调试命令:
go env+ls -la+cat .golangci.yml | head -20,确认配置存在且可读 - 临时加
--verbose参数运行,观察是否出现failed to load packages类错误 - 避免在 CI 中用
golangci-lint run ./...指定子目录,应确保工作目录就是 module 根目录


















