gofmt -w . 是唯一必须执行的格式化命令,需在含 go.mod 的模块根目录运行以递归处理所有 .go 文件;golangci-lint 是静态检查入口,不可替代;revive 需显式配置规则并设 severity="error" 才生效;//nolint 仅限明确场景下谨慎使用。

gofmt -w 是唯一必须跑通的命令
Go 代码格式没有商量余地,gofmt 就是最终仲裁者。它硬编码了所有规则:缩进用 tab、运算符前后必须空格、函数括号不换行、import 分组顺序固定——你改不了,也不该改。
日常唯一要记住的是:gofmt -w .。必须在含 go.mod 的模块根目录执行,它会递归处理所有 .go 文件。
- 别写
gofmt -w *.go:漏掉子目录里的文件 - 别写
gofmt -w ./:末尾斜杠在某些 shell 下触发路径解析异常 - CI 中用
gofmt -d .预览差异,有输出就失败,直接git checkout -- .再gofmt -w . - 报错
no Go files in??先ls go.mod确认是否在模块根目录,再which gofmt看是不是$GOROOT/bin/gofmt
golangci-lint 是检查入口,不是可选项
团队不用 golangci-lint,等于把 go vet、errcheck、revive 全手动轮着跑。它不是“多一个工具”,而是让所有静态检查收敛到一条命令里。
golint 已于 2021 年归档废弃,它只做风格检查、不支持并行/缓存/配置过滤,且与真实隐患检测器(如 govet)冲突。VS Code 里设 go.lintTool: "golint" 会导致保存时反复卡顿或报错。
Go 配置库,使用 spf13/viper — 分层优先级(flag > env >file > KV > default),提供 BindPFlag/BindPFlags、SetEnvPrefix + SetEnvKeyReplace 等功能。
立即学习“go语言免费学习笔记(深入)”;
- 最小可用命令:
golangci-lint run --fast --timeout=60s --exclude-dirs=testdata,vendor --skip-dirs-use-default=false -
--fast跳过staticcheck等耗时分析器,适合本地快速验证 -
--exclude-dirs必须显式声明,否则testdata/里的非法示例会被当成正式代码报错 - 不加
--config时,它自动查找项目根目录的.golangci.yml;没找到就用内置默认规则
revive 配置必须显式启用规则
revive 替代 golint,但默认不开任何检查项——装完不配 .revive.toml,等于没装。常见踩坑点是以为“装了就自动查”,结果 revive ./ 什么也不报。
- [rule.exported] 控制首字母大写的导出符号命名,不是
exported-name - [rule.blank-imports] 检查
import _ "net/http/pprof"类导入,不是blank_import -
severity设为"error"才会让 CI 失败;设"warning"仅提示,CI 不拦 - 最小可用配置示例:
[rule.exported] severity = "error" [rule.blank-imports] severity = "error"
//nolint 不是万能胶布,乱用会关掉安全阀
//nolint 只应在明确知道后果的前提下局部绕过:
- 单行忽略指定 linter:
log.Println("debug") //nolint:logrange(注意冒号后不能有空格) - 忽略整个函数:在函数签名上一行加
//nolint:unparam,funlen,多个用英文逗号分隔 - 禁止在
main.go或错误处理路径里用//nolint:errcheck——这等于主动关闭安全阀 - 自动生成的 protobuf 代码优先在
.golangci.yml的exclude-files里加正则:^.*_pb\.go$,而非在文件顶部写//nolint
真正难的不是写 linter,是让团队持续用起来。格式和基础检查能自动化,但业务逻辑约束、上下文感知的误报抑制、以及开发者对 //nolint 的克制意识,这些没法靠配置解决。

















