
一份有态度的Go代码规范指南
一份有态度的Go代码规范指南
不是官方案例,是实战经验。
痛点
每个Go项目都有自己的风格。
- 有的返回接口,有的返回结构体
- 有的用sentinel错误,有的全包一层
- 有的包自己打日志,有的只返回错误
- 有的强制pkg/目录结构,有的很随意
AI写Go代码,该听谁的?
go-style-agent-skill 是什么
madflojo(Benjamin Cane)开源的观点鲜明的Go代码规范Skill——
一套实用的Go工程决策指南,覆盖包设计、构造函数、接口、错误处理、日志、文档、布局、基准测试等核心主题。
核心特点
- 🎯 观点鲜明 — 不是官方案例,是实战经验
- 📦 结构化 — 主技能 + 10个参考文档
- 🤖 AI友好 — 专为coding agents设计
- 👥 人类可用 — 工程师也能直接用
- ⚡ 按需加载 — 只读需要的参考文档
10个核心原则
1. 可测试性优先
设计为了信心,不是为了覆盖率百分比。
怎么做:
- 注入依赖,保持逻辑纯粹
- 测试edge case和misuse path,不只是happy path
- 并发代码跑
-race
2. Config驱动构造函数
Config in → concrete struct out
type Config struct {
Port int
Timeout time.Duration
}
func New(cfg Config) (*Service, error) {
if cfg.Port <= 0 {"
return nil, errors.New("invalid port")
}
// 应用默认值
if cfg.Timeout == 0 {
cfg.Timeout = 30 * time.Second
}
return &Service{cfg: cfg}, nil
}关键点:
- 验证 + 默认值在
New里做 - Config逻辑复杂时用
Config.Validate() - 返回具体类型,不是接口
3. 接口:接受接口,返回结构体
消费者通常定义接口。
// 好的:消费者定义
type Reader interface {
Read() ([]byte, error)
}
// 不好的:包返回接口
func NewService() (Service, error) // 别这样例外: 共享契约包(比如database/sql)。
4. 错误是契约
- 用sentinel错误做持久化分支
- 其余用
%w或errors.Join包裹 recover只在应用边界
var ErrNotFound = errors.New("not found")
if err != nil {
if errors.Is(err, ErrNotFound) {
// 处理特定错误
}
return fmt.Errorf("operation failed: %w", err)
}5. 包可重用
- 没有隐藏的全局变量
- 没有默认日志
- 没有惊喜副作用
包返回错误,应用决定怎么记录。
6. 标准库优先
第三方库必须证明价值:
- 解决真实问题
- 积极维护
- 值得传递依赖成本
标准库不够清晰时才引入第三方。
7. 地道godoc
为公共和重要内部代码写文档。
- 遵循godoc惯例
- 写耐用的注释
- 别加agent-context注释(比如"AI generated")
8. 性能敏感代码要基准测试
- 对hot path做benchmark
- 用
b.ReportAllocs() - 用
benchstat对比运行
没benchmark的性能声明都是耍流氓。
9. 保持main.go瘦
只做wiring,业务逻辑别放这。
10. 遵循仓库现有惯例
别强推house目录结构。
如果仓库已有清晰惯例,那些惯例优先。
结构化设计
skills/
go-style-guide/
SKILL.md # 主技能入口
references/
BENCHMARKS.md # 基准测试
CONFIG.md # 配置与构造函数
CONCURRENCY.md # 并发
DOCUMENTATION.md # 文档与注释
ERRORS.md # 错误处理
INTERFACES.md # 接口
LAYOUT.md # 布局
LOGGING.md # 日志
REVIEW-CHECKLIST.md # 审查清单
TESTING.md # 测试设计哲学:
SKILL.md— 主技能提示,总是加载references/*.md— 按需读取,只读任务需要的
为什么?
避免加载不相关的内容,保持context精简。
快速规则表
| 主题 | 规则 | 参考 |
|---|---|---|
| 可测试性 | 设计为了信心,不只是覆盖率;测试edge和misuse case | TESTING.md |
| 构造函数 | Config in → concrete struct out;验证+默认值在New | CONFIG.md |
| 错误 | 用sentinel做分支;用%w或errors.Join包裹;recover在边界 | ERRORS.md |
| 日志 | 包默认不记录日志;hot-path日志是性能决策 | LOGGING.md |
| 依赖 | 标准库优先;第三方必须有明确价值 | LAYOUT.md |
| 接口 | "接受接口,返回结构体";消费者通常定义接口 | INTERFACES.md |
| 文档 | 写地道godoc和耐用注释;别加agent-context注释 | DOCUMENTATION.md |
| 布局 | 包保持浅层;避免杂物抽屉;遵循仓库惯例 | LAYOUT.md |
| 入口点 | main.go只做wiring | LAYOUT.md |
| 基准测试 | 对hot path做benchmark;用b.ReportAllocs()和benchstat | BENCHMARKS.md |
| 测试 | 表驱动;标准库优先;防御misuse;输入复杂时fuzz | TESTING.md |
| 并发 | 每个goroutine需要shutdown path;用context、-race、jitter | CONCURRENCY.md |
| 审查 | 审查Go改动时用checklist | REVIEW-CHECKLIST.md |
常见陷阱
❌ 返回接口而非具体类型
✅ 返回具体类型,让消费者定义接口
❌ 把覆盖率百分比当正确性证明
✅ 测试edge case和misuse path
❌ 可重用包自己打日志
✅ 返回错误,让应用决定怎么记录
❌ 标准库够清晰时加框架或helper库
✅ 标准库优先
❌ 通过包传递全局app config
✅ 用本地Config
❌ 关键运行时开关用危险默认值
✅ 显式验证和默认值
❌ 把house目录结构强推给已有惯例的仓库
✅ 遵循仓库现有惯例
❌ 在不知道任务涉及哪个主题时就加载所有参考文档
✅ 按需加载,只读相关的
❌ 声称性能提升但没有benchmark,或并发安全但没有-race
✅ 性能声明需要benchmark,并发代码要跑-race
执行协议
用这个技能做实现工作时,遵循这个工作流:
1. 先检查仓库
读现有包布局、构造函数、测试、错误惯例,再提新API或移动文件。
2. 先定义契约
提前决定:
- 包边界
- Config形状
- 具体返回类型
- Sentinel错误
- 依赖seam
- Context或shutdown期望
3. 尽早写或更新测试
从表驱动单元测试开始,为解析或输入密集代码加fuzz测试,为性能敏感路径加benchmark。
4. 实现最小可维护变更
遵循仓库现有布局,保持main.go瘦,避免在没明确边界时引入新抽象。
5. 运行收尾检查
- 用
gofmt格式化(如果仓库用goimports也跑) - 跑相关
go test目标 - 涉及并发时跑
go test -race - 声称性能改进时跑benchmark
6. 验证人面向契约
确保文档、注释、config默认值、错误行为匹配你发布的代码。
怎么用
GitHub CLI安装
gh skill install madflojo/go-style-agent-skillnpm skills安装
npx skills add -g -y madflojo/go-style-agent-skill手动安装
复制skills/go-style-guide/目录到:
- 你的仓库的
.agents/skills/ - 你的用户级
~/.agents/skills/
版本锁定
gh skill install madflojo/go-style-agent-skill@v1.0.0
gh skill install madflojo/go-style-agent-skill@<commit-sha>兼容性说明
例子假设现代Go,使用标准库特性如errors.Join和log/slog。
Go 1.21+是良好基线。
如果把指南应用到旧仓库,根据仓库实际支持的Go版本调整建议。
核心价值
go-style-agent-skill解决的不是"怎么写Go"的问题——
它解决的是"怎么写一致、可维护、生产级的Go"的问题。
观点鲜明,不是为了讨好所有风格偏好
实战导向,从真实项目提炼而非纸上谈兵
结构化设计,主技能 + 按需参考文档
AI友好,专为coding agents设计
人类可用,工程师也能直接参考
让AI和人类都写出有态度的Go代码。
项目地址:https://github.com/madflojo/go-style-agent-skill
作者:madflojo (Benjamin Cane)
协议:Apache-2.0
关注公众号 Fen9Pi,聊聊Go工程最佳实践。
