golangci-lint 默认跳过 vendor 但极易失效,因任何配置改动(如空 skip-dirs、错误路径、disable-all、跨目录调用等)均会覆盖默认行为;最稳妥做法是显式声明 run.skip-dirs: - vendor - testdata - internal/gen - mocks,并在多模块/CI/replace/go.work 场景中手动补充对应路径。

golangci-lint 默认就跳过 vendor 目录,但这个“默认”非常脆弱——只要配置里动了一行,它就可能失效。
为什么 vendor 还是被扫了?常见配置踩坑点
你以为没配就是安全的,其实不是。golangci-lint 的 vendor 跳过逻辑只在“完全没干扰默认行为”时才生效。以下情况都会让 vendor 重新进入扫描范围:
- 在
.golangci.yml中写了run.skip-dirs: [](空数组),这会覆盖默认值,而不是追加 - 启用了
disable-all: true却没手动补上skip-dirs块 - 路径写成
- ./vendor或- src/vendor,而配置文件所在目录是项目根,正确写法只能是- vendor - 用
golangci-lint run ./...从父目录调用子模块,工具不识别模块边界,vendor可能被当作普通目录递归进去
最稳妥的写法:显式声明 skip-dirs
别赌默认逻辑,直接在 .golangci.yml 的 run 区块里写死:
run:
skip-dirs:
- vendor
- testdata
- internal/gen
- mocks注意:skip-dirs 是相对于配置文件所在路径的相对路径,不支持通配符或 glob;多个目录用换行+短横线,不是逗号分隔。
立即学习“go语言免费学习笔记(深入)”;
CI 或多 module 项目中必须加这一行
本地跑得通 ≠ CI 跑得通。不同环境的 GOPATH、GO111MODULE、甚至 shell 解析行为都可能导致默认跳过失效。尤其在 monorepo 场景下:
- 子模块有自己的
go.mod,但父级配置没显式跳过vendor,golangci-lint 可能尝试解析其依赖树并卡住 - 某些 linter(如
staticcheck)需要类型信息,一旦误入vendor,会因 AST 不兼容直接 panic - GitHub Actions 中若未显式声明,
vendor扫描可能拖慢 lint 步骤至超时(默认timeout: 1m)
额外提醒:go.work 和 replace 场景要小心
如果你用 go.work 管理多模块,或在 go.mod 里写了 replace 指向本地路径,golangci-lint 仍会把那些本地路径当作“源码”而非第三方包来扫——它们不在 vendor 里,但属于第三方依赖。此时需手动加进 skip-dirs,比如:
run:
skip-dirs:
- vendor
- ../my-internal-lib # replace 指向的本地路径真正难处理的从来不是 vendor,而是那些被 replace 或 go.work 拉进来的“伪本地依赖”。它们不会自动跳过,必须人工识别并加入 skip-dirs。


















