关于 writing-go
writing-go 是面向 Go 开发者的技能资料,介绍标准库优先、组合设计和清晰错误处理等原则。内容包括实用代码模式、Go 1.25 特性、工具和常见陷阱。
主要功能
- 01错误处理与上下文包装
- 02选项模式和表驱动测试示例
- 03Go 1.25 特性概览
- 04构建、测试与 lint 工具
- 05并发和标准库常见陷阱
适用场景
- 01制定 Go 项目的开发规范
- 02为函数和服务设计错误处理
- 03编写表驱动测试并检查并发代码
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ julianobarbosa/ claude-code-skills --skill writing-go安装后在 Claude Code 中输入/writing-go确认已加载。
包含的文件
除 SKILL.md 外,安装时一起下载的参考资料和脚本。
CLI.mdPATTERNS.mdTESTING.md详细介绍
Go 开发(1.25+)
核心原则
- 标准库优先:只有在有充分理由时才使用外部依赖
- 具体类型:在使用方定义接口,返回结构体
- 组合:始终优先于继承
- 快速失败:提供清晰且包含上下文的错误
- 简单:通常最直观的解决方案就是正确的方案
快速模式
错误处理
if err := doThing(); err != nil {
return fmt.Errorf("do thing: %w", err)
}
带选项的结构体
type Server struct {
addr string
timeout time.Duration
}
func NewServer(addr string, opts ...Option) *Server {
s := &Server{addr: addr, timeout: 30 * time.Second}
for _, opt := range opts {
opt(s)
}
return s
}
表驱动测试
tests := []struct {
name string
input string
want string
wantErr bool
}{
{"valid", "hello", "HELLO", false},
{"empty", "", "", true},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
got, err := Process(tt.input)
if tt.wantErr {
require.Error(t, err)
return
}
require.NoError(t, err)
assert.Equal(t, tt.want, got)
})
}
Go 1.25 特性
- testing/synctest:使用模拟时钟进行确定性的并发测试
- encoding/json/v2:实验性功能,速度快 3–10 倍(GOEXPERIMENT=jsonv2)
- runtime/trace.FlightRecorder:按需捕获生产环境跟踪信息
- 感知容器的 GOMAXPROCS:自动检测 cgroup 限制
- GreenTea GC:实验性功能,可降低延迟(GOEXPERIMENT=greenteagc)
参考资料
- PATTERNS.md - 详细的代码模式
- TESTING.md - 使用 testify/mockery 的测试策略
- CLI.md - CLI 应用程序模式
工具
go build ./... # Build
go test -race ./... # Test with race detector
golangci-lint run # Lint
mockery --all # Generate mocks
注意事项
- 向
nil通道发送或从中接收会永远阻塞;从已关闭的通道接收会立即返回零值 — 在select中,nil通道对应的分支会被禁用。这种模式很有用,但也容易无意中触发。 defer会在调用时而非执行时捕获参数 —defer fmt.Println(time.Now())捕获的是此刻的时间,而不是延迟执行时的时间。- Go 1.22 之前,for 循环中的闭包会在所有迭代中捕获同一个变量 — 这就是循环中启动 goroutine 时的常见问题。Go 1.22 更改了语义;在混合版本代码中,沿用旧习惯会造成微妙的错误。
errors.Is会遍历Unwrap()链,但如果被包装的错误本身实现了Is(target error) bool,则会优先调用自定义的 Is 方法,而不遍历链 — 从 xerrors 迁移时,这一点容易令人困惑。sync.Pool中的项可能会在Get和下一次Put之间被 GC 回收 — 切勿依赖 Pool 保留状态。
评论
支持 Markdown