golangci-lint 默认不检查未导出方法的命名规范或可见性问题,这类检查需依赖 revive;unused 仅标记未被调用的未导出函数,staticcheck 不检查方法可见性,真正可见性错误由编译器捕获。

golangci-lint 默认不检查未导出方法的可见性问题
它根本不会报「未导出方法命名不规范」或「小写方法被意外暴露」这类问题——因为这不是 golangci-lint 的职责范围,也不是 Go 编译器或 vet 的检查目标。所谓“代码可见性规则”,在 Go 里本质是包级封装约定:func doSomething() 是私有,func DoSomething() 是导出,仅此而已;工具不会强制你“不该写小写方法”,也不会警告“这个私有方法名字太长”。
真正能查命名风格的是 revive,不是 golint 或 staticcheck
如果你关心未导出标识符(如 myHelper、parseJSONStr)是否符合团队内部命名习惯(比如要求私有函数也用驼峰、禁止下划线),就得靠 revive,它是 golint 的现代替代品,支持自定义规则。
-
revive启用后,可通过exported规则检查导出项命名,通过var-naming/func-naming检查所有变量/函数(含未导出)是否符合正则模式 - 在
.golangci.yml中启用:linters-settings: revive: rules: - name: func-naming arguments: ["^[a-z][a-z0-9]*([A-Z][a-z0-9]*)*$"] - 注意:
revive不会误报init、main这类特殊函数,但会对handle_user_request这种带下划线的私有函数发出警告
staticcheck 和 unused 对未导出方法的行为差异
这两个 linter 看似和“私有方法”有关,但逻辑完全不同:
-
unused会标记未被调用的未导出函数(如func helper() {}从没被引用),但它不关心你有没有导出它,只关心“有没有人用” -
staticcheck的SA4013规则会警告“未使用的 struct 字段”,但对方法无感;它也不会因为你写了func (t *T) String() string却没实现fmt.Stringer就报错——那是govet的methods检查干的事 - 真正会因可见性出问题的是跨包调用:比如你在
pkg/a里写了func doX(),又在pkg/b里试图a.doX()——这压根编译不过,golangci-lint连看都不会看这一行
为什么你看到的“未导出方法检测”往往是误判或配置错位
常见假阳性来源:
- 把
golint当成有效工具:它确实曾检查私有变量命名,但它已于 2022 年归档,且对泛型、嵌套类型等完全失效;现在运行golint ./只会漏掉大量真实问题 -
.golangci.yml放错位置:比如放在internal/子目录而非go.mod所在根目录,导致revive根本没加载,你以为没效果,其实是配置没读到 - 混淆了“未使用”和“不应存在”:一个未导出方法只要被同包内调用过,
unused就不会动它;你不能指望 lint 工具替你做架构决策,比如“这个 helper 太复杂,应该拆成两个”
真正的可见性风险不在命名,而在接口设计——比如把 func (c *Client) doRequest() 设为未导出,却在文档里公开了调用方式,这种矛盾只能靠人工 review,工具无能为力。
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!











