mcpField
G
go-code-review

go-code-review

github.com/cxuu测试与质量1861.7k 次安装19 周前更新
代码仓库

关于 go-code-review

面向 Go 开发者的代码审查技能,提供结构化检查清单。它结合自动化预审与 Go 专项指南,并按严重程度整理审查结果。

主要功能

  1. 01运行 gofmt、go vet 和 golangci-lint 预检
  2. 02检查 Go 风格、错误、并发与安全
  3. 03按规则名和代码行标注问题
  4. 04按严重程度组织审查结果

适用场景

  1. 01合并前审查 Go 代码变更
  2. 02检查 HTTP 服务代码中的并发与关闭问题
  3. 03统一整理必须修复、建议修复和细微问题

安装

复制下面的命令,在终端中运行。

$npx skills add https://github.com/cxuu/golang-skills --skill go-code-review

安装后在 Claude Code 中输入/go-code-review确认已加载。

包含的文件

除 SKILL.md 外,安装时一起下载的参考资料和脚本。

assets/
review-template.md
references/
WEB-SERVER.md
scripts/
pre-review.sh

详细介绍

Go 代码审查清单

兼容性:references/WEB-SERVER.md 中的 log/slog 示例需要 Go 1.21+。

资源路由

  • assets/review-template.md - 格式化审查结果时使用,包含 Must Fix、Should Fix 和 Nits 部分。
  • scripts/pre-review.sh - 手动审查前运行,以收集 gofmt、go vet 和 golangci-lint 的结果。
  • references/WEB-SERVER.md - 审查结合了并发、上下文、日志记录、错误处理和关闭行为的 HTTP 服务时阅读。

审查流程

格式化代码审查结果时使用 assets/review-template.md,以确保结构一致,并按 Must Fix / Should Fix / Nits 严重程度分组。

  1. 先运行 gofmt -d . 和 go vet ./...,找出机械性问题
  2. 逐个文件阅读差异;对每个文件,按以下顺序检查各类别
  3. 标出问题的具体行号和规则名称
  4. 审查完所有文件后,重新检查已标出的问题,确认它们确实存在
  5. 按严重程度(必须修复、应该修复、小问题)汇总发现

验证:完成审查后,再次阅读差异,确认每个标出的问题都确实存在。删除任何无法用具体行号证明的问题。


格式

  • gofmt:代码已使用 gofmt 或 goimports 格式化 → go-linting

文档

  • 注释句子:注释为完整句子,以所描述对象的名称开头,并以句号结尾 → go-documentation
  • 文档注释:所有导出名称都有文档注释;非简单的未导出声明也有文档注释 → go-documentation
  • 包注释:包注释紧邻 package 子句,中间没有空行 → go-documentation
  • 命名结果参数:仅在能明确含义时使用(例如,有多个相同类型的返回值),不要仅为启用裸返回而使用 → go-documentation

错误处理

  • 处理错误:不要用 _ 丢弃错误;应处理、返回错误,或(特殊情况下)触发 panic → go-error-handling
  • 错误字符串:使用小写字母,不带标点(以专有名词或缩写开头时除外)→ go-error-handling
  • 带内错误:不要使用魔法值(-1、""、nil);应通过多返回值中的 error 或 ok 布尔值表示 → go-error-handling
  • 错误流程缩进:优先处理错误并返回;尽量减少正常流程的缩进 → go-error-handling

命名

  • MixedCaps:使用 MixedCaps 或 mixedCaps,不要使用下划线;未导出名称使用 maxLength,而不是 MAX_LENGTH → go-naming
  • 首字母缩写:大小写保持一致:URL/url、ID/id、HTTP/http(例如 ServeHTTP、xmlHTTPRequest)→ go-naming
  • 变量名:作用域有限时使用短名称(i、r、c);作用域更广时使用较长名称 → go-naming
  • 接收者名称:使用类型名称的一或两个字母缩写(Client 使用 c);不要使用 this、self、me;各方法中保持一致 → go-naming
  • 包名:避免名称重复(使用 chubby.File,而不是 chubby.ChubbyFile);避免使用 util、common、misc → go-packages
  • 避免使用内置名称:不要遮蔽 error、string、len、cap、append、copy、new、make → go-declarations

并发

  • Goroutine 生命周期:明确 goroutine 是否以及何时退出;如果不明显,请记录 → go-concurrency
  • 同步函数:优先使用同步函数而非异步函数;如有需要,让调用方添加并发 → go-concurrency
  • 上下文:作为第一个参数;不放在结构体中;不使用自定义 Context 类型;即使认为不需要,也要传递 → go-context

接口

  • 接口位置:在消费者包中定义,而非实现方;生产方返回具体类型 → go-interfaces
  • 不要过早定义接口:在实际使用前不要定义;不要在实现方一侧为了“模拟”而定义 → go-interfaces
  • 接收者类型:如果会修改数据、包含同步字段或体积较大,则使用指针;小型不可变类型使用值;不要混用 → go-interfaces

数据结构

  • 空切片:优先使用 var t []string(nil),而非 t := []string{}(非 nil 的零长度切片)→ go-data-structures
  • 复制:复制带有指针/切片字段的结构体时要谨慎;不要按值复制 *T 方法的接收者 → go-data-structures

安全

  • 密码学随机数:密钥使用 crypto/rand,不要使用 math/rand → go-defensive
  • 不要 panic:正常错误处理应使用错误返回值;仅在真正异常的情况下使用 panic → go-defensive

声明和初始化

  • 分组相似项:相关的 var/const/type 放在带括号的代码块中;不相关的项分开 → go-declarations
  • var 与 :=:有意使用零值时用 var;显式赋值时用 := → go-declarations
  • 缩小作用域:将声明移至靠近使用的位置;使用 if-init 限制变量作用域 → go-declarations
  • 结构体初始化:始终使用字段名;省略零值字段;零值结构体使用 var → go-declarations
  • 使用 any:新代码中优先使用 any,而非 interface{} → go-declarations

函数

  • 文件顺序:类型 → 构造函数 → 导出方法 → 未导出方法 → 工具函数 → go-functions
  • 签名格式:换行时,所有参数各占一行,并在末尾加逗号 → go-functions
  • 未命名参数:对于含义不明确的 bool/int 参数,添加 /* name */ 注释,或使用自定义类型 → go-functions
  • Printf 命名:接受格式字符串的函数名称以 f 结尾,以便通过 go vet 检查 → go-functions

风格

  • 行长:没有严格限制,但应避免过长的行;按语义换行,而非按任意长度换行 → go-style-core
  • 裸返回:仅用于短函数;中型/大型函数使用显式返回 → go-style-core
  • 传递值:不要仅为了节省字节而使用指针;对于小型固定大小类型,传递 string 而非 *string → go-performance
  • 字符串拼接:简单拼接使用 +;格式化使用 fmt.Sprintf;循环中使用 strings.Builder → go-performance

日志记录

  • 使用 slog:新代码使用 log/slog,而非 log 或 fmt.Println 进行运行日志记录 → go-logging
  • 结构化字段:日志消息使用静态字符串和键值属性,而非 fmt.Sprintf → go-logging
  • 使用适当的级别:Debug 用于开发者跟踪,Info 用于值得关注的事件,Warn 用于可恢复的问题,Error 用于失败 → go-logging
  • 日志中不记录机密信息:绝不记录个人身份信息、凭据和令牌 → go-logging

导入

  • 导入分组:先导入标准库,然后空一行,再导入外部包 → go-packages
  • 导入重命名:除非名称冲突,否则避免重命名;发生冲突时重命名本地/项目专用导入 → go-packages
  • 空白导入:import _ "pkg" 仅用于 main 包或测试 → go-packages
  • 点导入:仅用于测试中的循环依赖变通方案 → go-packages

泛型

  • 适用场景:仅当多种类型共享相同逻辑且接口无法满足需求时使用 → go-generics
  • 类型别名:新类型使用类型定义;别名仅用于包迁移 → go-generics

测试

  • 示例:包含可运行的 Example 函数或演示用法的测试 → go-documentation
  • 有用的测试失败信息:消息应包含错误原因、输入、实际值和期望值;顺序为 got != want → go-testing
  • TestMain:仅在所有测试都需要共同的设置和清理时使用;优先考虑作用域限定的辅助函数 → go-testing
  • 真实传输:优先使用 httptest.NewServer 和真实客户端,而非模拟 HTTP → go-testing

自动化检查

运行自动化的审查前检查:

bash scripts/pre-review.sh ./...         # text output
bash scripts/pre-review.sh --json ./...  # structured JSON output

或者手动运行:gofmt -l <path> && go vet ./... && golangci-lint run ./...

继续执行上述清单前,请先修复所有问题。有关 linter 的设置和配置,请参阅 go-linting。


相关技能

  • 风格基础:在解决格式争议或应用清晰度 > 简洁性 > 精炼性的优先级时,请参阅 go-style-core
  • Linting 设置:在配置 golangci-lint 或向 CI 添加自动化检查时,请参阅 go-linting
  • 错误处理策略:在审查错误包装、哨兵错误或仅处理一次模式时,请参阅 go-error-handling
  • 命名约定:在评估标识符名称、接收者名称或包符号重复时,请参阅 go-naming
  • 测试模式:在审查测试代码中的表驱动结构、失败信息或辅助函数用法时,请参阅 go-testing
  • 并发安全:在审查 goroutine 生命周期、通道用法或互斥锁位置时,请参阅 go-concurrency
  • 日志实践:在审查日志用法、结构化日志或 slog 配置时,请参阅 go-logging

评论

支持 Markdown