golangci-lint启用前必须禁用golint、unused、deadcode三个高噪声linter;应聚焦启用errcheck、staticcheck(限sa1012/sa1014/sa1019)、gosec这三个覆盖资源泄漏、错误忽略、不安全调用的核心安全检查器。

直接说结论:静态安全检测不是“装上就安全”,而是要分阶段、选对工具、避开高噪声规则,否则新手会被误报淹没,反而忽略真正该学的安全基础。
golangci-lint 启用前必须禁用的三个 linter
新手一上来就 golangci-lint init 生成默认配置,大概率会触发大量无关警告,比如未导出函数没注释(golint)、未使用的私有方法(unused)、结构体字段未被引用(structcheck)。这些和代码安全性无关,纯属工程成熟度问题。
-
golint已归档,官方明确不维护,规则主观且噪音大,必须在.golangci.yml中加入disable: ["golint"] -
unused和deadcode在小型项目或原型阶段几乎必报,但它们反映的是代码组织问题,不是安全漏洞,建议初期禁用:disable: ["unused", "deadcode"] - 若项目还没写测试,
testpackage会报“包名不是 _test”,也属于干扰项,一并禁用
真正值得开的静态安全检查器(只配这 3 个)
安全类问题集中在资源泄漏、错误忽略、不安全调用三类。没必要启用全部 15+ linter,以下三个覆盖 90% 高危模式:
-
errcheck:强制检查每个error返回值是否被处理。常见漏点:os.Remove、io.Copy、http.Client.Do后忽略 error -
staticcheck:启用SA1019(过时 API)、SA1012(未设置http.Request.Header)、SA1014(未关闭io.ReadCloser)等关键子规则 -
gosec:专为安全设计的 linter,能识别硬编码密码、unsafe使用、crypto/md5等弱哈希调用 —— 它不包含在 golangci-lint 默认集成中,需单独安装并显式启用
配置示例(.golangci.yml 片段):
linters:
enable:
- errcheck
- staticcheck
- gosec
linters-settings:
errcheck:
check-type-assertions: true
staticcheck:
checks: ["SA1012", "SA1014", "SA1019"]
gosec:
excludes: ["G104"] # 可选:跳过“忽略 err”类检查,留给 errcheck 处理
gosec 必须手动安装且注意版本兼容性
gosec 不是 golangci-lint 的内置 linter,不执行 go install github.com/securego/gosec/cmd/gosec@latest 就无法启用。但要注意:
- Go 1.21+ 项目若用
gosec v2.14.0+,需确认其支持模块路径解析,否则扫描会跳过 vendor 或嵌套模块 - 运行
gosec ./...单独验证是否生效,常见错误:command not found: gosec→ 检查$(go env GOPATH)/bin是否在$PATH - 它默认扫描所有文件,包括
testdata/和mocks/,建议在.gosec.yaml中配置exclude:列表,否则 mock 文件里硬编码的 token 会误报
CI 中跑静态安全检查最容易忽略的两件事
很多团队把 golangci-lint run 加进 GitHub Actions 就以为万事大吉,但实际常因两个细节失败:
- 没设超时:大型项目跑
staticcheck+gosec可能超 5 分钟,默认 timeout 是 1m,CI 直接中断 → 必须加--timeout=8m - 没缓存二进制:每次 CI 都重装
golangci-lint和gosec,浪费时间还易因网络失败 → 应用actions/cache缓存$(go env GOPATH)/bin/下的可执行文件 - 更隐蔽的问题:
gosec对go.mod里 replace 指向本地路径的模块可能扫描失败,这种依赖需在 CI 中先go mod download再扫描
安全不是靠工具堆出来的,而是靠每次提交时真实暴露的那几个 SA1014 或 G101 警告,逼你多写一行 defer resp.Body.Close()。工具链越简单、规则越聚焦,越容易形成条件反射式的安全习惯。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











