golangci-lint 扫描慢主因是配置不当:未跳过 vendor/testdata/生成代码等目录、缓存路径不固定或失效、并发数设置过高;优化后中小项目耗时可从42s降至6s。

golangci-lint 扫描慢,90% 是配置没筛对目录、没稳住缓存、或并发和超时互相拖后腿——不是工具本身慢,是它在反复干无用功。
跳过 vendor/testdata/生成代码这些“假代码”目录
默认会递归扫描全部子目录,vendor 里几万行第三方代码全被加载解析,类型检查直接卡住。实测跳过 vendor 后,中小项目耗时从 42s 降到 6s。
- 命令行加
--skip-dirs vendor,testdata,examples,scripts(Linux/macOS 用英文逗号;Windows 建议用 WSL 或改分号) - 配置文件里写
run.skip-dirs,比在linters-settings里 disable 某个 linter 快得多——过滤越早,解析负担越小 - 别依赖
.gitignore:golangci-lint 默认不读它,除非显式设run.skip-dirs-use-default: true且exclude-use-default: false - 生成代码(如
pb.go、stringer_string.go)也得跳过,否则 staticcheck 会在泛型展开后做冗余推导,Go 1.22+ 尤其明显
缓存路径必须固定,且 CI 要挂载复用
缓存失效是 CI 中“偶发变慢”的根因。GOLANGCI_LINT_CACHE 指向临时路径(比如 /tmp)或每次 job 都清空,等于没开缓存。
- 本地开发:设环境变量
GOLANGCI_LINT_CACHE=$HOME/.cache/golangci-lint,确保路径稳定 - GitHub Actions:必须用
actions/cache持久化/tmp/golangci-cache,并在 job 中设GOLANGCI_LINT_CACHE: /tmp/golangci-cache - GitLab CI:用
cache:paths缓存对应路径,避免每次重装模块 - 验证是否生效:加
-v运行一次,日志里看到cache hit或loaded from cache才算成功
并发数别碰 CPU 核心数,默认值在 CI 上大概率翻车
concurrency 设太高不会提速,反而触发 GC 频繁、内存带宽打满,导致单个 linter 实例响应变慢,总耗时不降反升。
立即学习“go语言免费学习笔记(深入)”;
- 中小型项目(concurrency: 2 到
.golangci.yml的run段,比依赖本地 CPU 数更稳 - 大型单体项目:可试
concurrency: 4,但必须配合skip-dirs和modules-download-mode: "readonly",否则 replace 本地 module 时会抢go.mod锁而卡死 - 绝对别写
concurrency: 0:它不是自动适配,而是退化成单线程,耗时可能翻 3–5 倍 - 真实瓶颈不在 CPU,而在
go/types加载——它吃内存带宽和 GC 压力,不是纯计算密集型
timeout 和 concurrency 组合要保守,尤其 Go 版本升级后
Go 1.22+ 对泛型的类型推导更细,staticcheck 单次分析耗时上升 30–50%,原来够用的 timeout 可能突然不够。
- 本地开发:
timeout: 2m足够,改完代码基本秒出结果 - CI 流水线:
timeout: 5m起步,若频繁超时,先查缓存和 skip-dirs 是否生效,而不是盲目调高 concurrency - 别用
--fast换 timeout:它跳过unused、staticcheck等核心 linter,漏检风险极高 - 最稳组合是:
concurrency: 2–3+timeout: 3–5m+skip-dirs+ 固定缓存路径 —— 数字本身不难调,难的是不同 Go 版本下同一组参数表现差异很大
真正容易被忽略的点是:模块解析模式和 Go 版本的耦合。比如 modules-download-mode: "readonly" 在 Go 1.21 下只是优化,在 Go 1.22+ 下却是避免并发锁死的必要条件——不看版本盲配,再好的参数也白搭。


















