关于 go-style-core
go-style-core 为编写 Go 代码提供按优先级组织的可读性与格式规范,适用于希望统一风格并改善可维护性的开发者。内容涵盖格式、控制流和返回值等实践。
主要功能
- 01按优先级指导代码风格
- 02强调 gofmt 与语义换行
- 03建议减少嵌套和多余分支
- 04说明裸返回的适用范围
适用场景
- 01编写易读的 Go 代码
- 02审查代码中的控制流与格式
- 03处理风格原则之间的取舍
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ cxuu/ golang-skills --skill go-style-core安装后在 Claude Code 中输入/go-style-core确认已加载。
附带文件references/FORMATTING.mdreferences/PRINCIPLES.md
详细介绍
Go 风格核心原则
资源路由
references/PRINCIPLES.md- 在处理清晰性、简单性、简洁性、可维护性和一致性之间的冲突时阅读。references/FORMATTING.md- 在处理 gofmt、换行、空白、注释或分号时阅读。
风格原则(按优先级排序)
编写易读的 Go 代码时,请按重要性顺序应用以下原则:
优先级顺序
- 清晰性 — 读者无需额外上下文就能理解代码吗?
- 简单性 — 这是实现目标最简单的方式吗?
- 简洁性 — 每一行代码都有其存在的价值吗?
- 可维护性 — 以后修改起来容易吗?
- 一致性 — 这是否符合周围的代码和项目约定?
格式化
运行 gofmt——没有例外。没有严格的行长限制,但 Uber 建议将 99 个字符作为软性限制。按语义拆分,而不是按长度拆分——应重构代码,而不是只做换行。
减少嵌套
优先处理错误情况和特殊条件。尽早返回或继续循环,避免“正常流程”产生缩进。
// Bad: Deeply nested
for _, v := range data {
if v.F1 == 1 {
v = process(v)
if err := v.Call(); err == nil {
v.Send()
} else {
return err
}
} else {
log.Printf("Invalid v: %v", v)
}
}
// Good: Flat structure with early returns
for _, v := range data {
if v.F1 != 1 {
log.Printf("Invalid v: %v", v)
continue
}
v = process(v)
if err := v.Call(); err != nil {
return err
}
v.Send()
}
不必要的 else
如果变量在 if 的两个分支中都会赋值,请使用“默认值 + 覆盖”模式。
// Bad: Setting in both branches
var a int
if b {
a = 100
} else {
a = 10
}
// Good: Default + override
a := 10
if b {
a = 100
}
裸返回
不带参数的 return 语句会返回已命名的返回值。这称为“裸返回”。
func split(sum int) (x, y int) {
x = sum * 4 / 9
y = sum - x
return // returns x, y
}
裸返回指南
- 小函数中可以使用:只有寥寥几行的函数可以使用裸返回
- 中等及以上规模的函数应明确返回值:函数达到中等规模后,应明确写出返回值,以提高清晰度
- 不要只为裸返回而命名返回值:文档的清晰度始终比省下一两行代码更重要
// Good: Small function, naked return is clear
func minMax(a, b int) (min, max int) {
if a < b {
min, max = a, b
} else {
min, max = b, a
}
return
}
// Good: Larger function, explicit return
func processData(data []byte) (result []byte, err error) {
result = make([]byte, 0, len(data))
for _, b := range data {
if b == 0 {
return nil, errors.New("null byte in data")
}
result = append(result, transform(b))
}
return result, nil // explicit: clearer in longer functions
}
有关命名返回参数的指导,请参阅 go-documentation。
分号
Go 词法分析器会在以下行末自动插入分号:末尾 token 为标识符、字面量,或以下任一项:break continue fallthrough return ++ -- ) }。
这意味着左花括号必须与控制结构写在同一行:
// Good: brace on same line
if i < f() {
g()
}
// Bad: brace on next line — lexer inserts semicolon after f()
if i < f() // wrong!
{ // wrong!
g()
}
符合 Go 惯例的代码只会在 for 循环子句中显式使用分号,或用分号分隔同一行上的多条语句。
快速参考
| 原则 | 核心问题 |
|---|---|
| 清晰性 | 读者能理解做了什么以及为什么这样做吗? |
| 简单性 | 这是最简单的实现方式吗? |
| 简洁性 | 信噪比高吗? |
| 可维护性 | 以后可以安全地修改吗? |
| 一致性 | 这是否符合周围的代码? |
相关技能
- 命名约定:应用 MixedCaps、选择标识符名称或解决命名争议时,请参阅 go-naming
- 错误流程:设计错误优先的守卫子句或通过提前返回减少嵌套时,请参阅 go-error-handling
- 文档:编写文档注释、命名返回参数或包级文档时,请参阅 go-documentation
- Lint 强制检查:使用 golangci-lint 自动执行风格检查或配置 CI 时,请参阅 go-linting
- 代码审查:在系统化代码审查中应用风格原则时,请参阅 go-code-review
- 日志风格:审查日志实践、选择 log 或 slog,或组织日志输出时,请参阅 go-logging
评论
支持 Markdown