关于 golang-master
面向 Go 开发者的编程技能,涵盖惯用设计、并发、错误处理、测试与性能分析,并附带代码检查和基准测试脚本。
主要功能
- 01Go 问题分类
- 02惯用设计指导
- 03并发模式
- 04错误处理策略
- 05测试与性能分析指导
- 06代码检查和基准测试脚本
适用场景
- 01设计 goroutine 协作方式
- 02追踪并包装错误
- 03规划表驱动测试
- 04运行项目代码检查
安装
复制下面的命令,在终端中运行。
$
npx skills add https:/ / github.com/ tomlord1122/ tomtom-skill --skill golang-master安装后在 Claude Code 中输入/golang-master确认已加载。
附带文件scripts/benchmark.shscripts/lint.sh
详细介绍
Go 语言专家
Go 语言精通领域的专家助手,涵盖并发模式、性能优化、标准库使用和测试策略。
思考过程
激活后,请遵循以下结构化思考方法来解决 Go 相关问题:
第 1 步:问题分类
目标: 了解这是哪一类 Go 问题。
需要思考的关键问题:
- 这是并发问题吗?(goroutine、通道、竞态条件)
- 这是性能问题吗?(内存、CPU、分配)
- 这是设计问题吗?(接口、结构体组合、包)
- 这是调试问题吗?(错误追踪、意外行为)
- 这是测试问题吗?(单元测试、基准测试、模拟)
决策点: 对问题进行分类,以选择合适的模式:
- 并发 → 检查竞态条件和同步方式是否恰当
- 性能 → 先进行性能分析,再优化
- 设计 → 应用接口隔离原则,以组合代替继承
- 调试 → 追踪错误链,检查 nil 处理
- 测试 → 表驱动测试、依赖注入
第 2 步:上下文分析
目标: 了解现有代码库的上下文和限制。
需要思考的关键问题:
- 使用的是哪个 Go 版本?(泛型需要 1.18+)
- 模块结构是什么样的?(标准布局还是扁平结构)
- 有哪些依赖?(标准库还是第三方库)
- 是否有需要遵循的现有模式?(错误处理风格、日志记录方式)
操作:
- 检查
go.mod中的 Go 版本和依赖 - 扫描现有代码,了解既定模式
- 识别任何特定于项目的约定
第 3 步:解决方案设计(符合 Go 惯用方式)
目标: 设计符合 Go 最佳实践的解决方案。
思考框架——应用以下原则:
-
简单优先
- “有没有更简单的实现方式?”
- 避免过度设计;Go 倾向于明确表达
-
错误处理
- “这里可能发生什么错误?应该如何传递错误?”
- 使用
fmt.Errorf("context: %w", err)包装错误 - 为特定领域的错误定义自定义错误类型
-
并发安全
- “是否有多个 goroutine 访问此数据?”
- “我需要互斥锁、通道还是原子操作?”
- 优先使用通道进行协调,使用互斥锁保护状态
-
接口设计
- “需要什么行为,而不是需要什么数据?”
- 保持接口精简(1–3 个方法)
- 接受接口,返回具体类型
-
资源管理
- “哪些资源需要关闭或清理?”
- 使用 defer 进行清理
- 传递 context 以支持取消操作
第 4 步:应用模式进行实现
目标: 恰当地应用常见的 Go 模式。
模式选择指南:
| 问题类型 | 推荐模式 |
|---|---|
| 并发处理 N 个项目 | Worker Pool |
| 限制并发操作数量 | Semaphore |
| 为长时间运行的操作设置超时 | 带 Deadline 的 Context |
| 协调多个 goroutine | WaitGroup |
| 扇出/扇入处理 | 通道流水线 |
| 优雅关闭 | Context 取消 + 信号处理 |
决策点: 对于每种模式,思考:
- “为什么这种模式适用于这个问题?”
- “我需要处理哪些边缘情况?”
第 5 步:测试策略
目标: 确保代码正确且易于维护。
思考框架:
- “有哪些正常流程需要测试?”
- “哪些边缘情况可能导致问题?”
- “这段代码是否便于测试?如果不便于,我应该如何重构?”
测试清单:
- 对具有多种输入场景的函数使用表驱动测试
- 对并发代码进行竞态检测(
go test -race) - 对性能关键代码进行基准测试
- 为外部依赖模拟接口
步骤 6:审查与完善
**目标:**确保解决方案已达到可投入生产使用的状态。
最终检查:
- 所有错误均已处理,或已通过注释明确忽略
- 上下文已沿调用链传递
- 资源已正确关闭(defer、Close())
- 没有 goroutine 泄漏(已关闭 channel、已取消 context)
- 代码可测试(已注入依赖)
- 已为导出符号编写文档
用法
运行 Linter
bash /mnt/skills/user/golang-master/scripts/lint.sh [project-dir] [fix-mode]
参数:
project-dir- 项目目录(默认:当前目录)fix-mode- 设为true以自动修复问题(默认:false)
示例:
bash /mnt/skills/user/golang-master/scripts/lint.sh
bash /mnt/skills/user/golang-master/scripts/lint.sh ./my-project true
**运行:**go vet、gofmt、staticcheck、golangci-lint、go mod tidy
运行基准测试
bash /mnt/skills/user/golang-master/scripts/benchmark.sh [project-dir] [pattern] [profile-type]
参数:
project-dir- 项目目录(默认:当前目录)pattern- 要匹配的基准测试模式(默认:.)profile-type- 性能分析类型:none、cpu、mem、all(默认:none)
示例:
bash /mnt/skills/user/golang-master/scripts/benchmark.sh
bash /mnt/skills/user/golang-master/scripts/benchmark.sh . BenchmarkProcess cpu
bash /mnt/skills/user/golang-master/scripts/benchmark.sh ./myproject . all
文档资源
官方文档:
- Go 文档:
https://go.dev/doc/ - Effective Go:
https://go.dev/doc/effective_go - Go by Example:
https://gobyexample.com/ - uber-go/guide:
https://github.com/uber-go/guide
并发模式
工作池
func workerPool(jobs <-chan Job, numWorkers int) <-chan Result {
results := make(chan Result, len(jobs))
var wg sync.WaitGroup
for i := 0; i < numWorkers; i++ {
wg.Add(1)
go func() {
defer wg.Done()
for job := range jobs {
results <- process(job)
}
}()
}
go func() {
wg.Wait()
close(results)
}()
return results
}
带超时的 Context
func fetchWithTimeout(url string) ([]byte, error) {
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
req, err := http.NewRequestWithContext(ctx, "GET", url, nil)
if err != nil {
return nil, err
}
resp, err := http.DefaultClient.Do(req)
if err != nil {
return nil, err
}
defer resp.Body.Close()
return io.ReadAll(resp.Body)
}
信号量模式
type Semaphore struct {
sem chan struct{}
}
func NewSemaphore(n int) *Semaphore {
return &Semaphore{sem: make(chan struct{}, n)}
}
func (s *Semaphore) Acquire() { s.sem <- struct{}{} }
func (s *Semaphore) Release() { <-s.sem }
错误处理
包装错误
func processUser(id int) error {
user, err := fetchUser(id)
if err != nil {
return fmt.Errorf("failed to fetch user %d: %w", id, err)
}
if err := validateUser(user); err != nil {
return fmt.Errorf("validation failed for user %d: %w", id, err)
}
return nil
}
自定义错误类型
type NotFoundError struct {
Resource string
ID string
}
func (e *NotFoundError) Error() string {
return fmt.Sprintf("%s not found: %s", e.Resource, e.ID)
}
// Usage
if errors.Is(err, &NotFoundError{}) {
// Handle not found
}
错误检查
// Use errors.Is for sentinel errors
if errors.Is(err, sql.ErrNoRows) {
return nil, &NotFoundError{Resource: "user", ID: id}
}
// Use errors.As for error types
var netErr *net.OpError
if errors.As(err, &netErr) {
// Handle network error
}
性能分析
CPU 性能分析
# Run benchmark with CPU profile
go test -cpuprofile=cpu.prof -bench=.
go tool pprof cpu.prof
# Interactive commands
(pprof) top10
(pprof) web
(pprof) list FunctionName
内存性能分析
# Run benchmark with memory profile
go test -memprofile=mem.prof -bench=.
go tool pprof -alloc_space mem.prof
# Check for allocations
go build -gcflags='-m' ./...
基准测试示例
func BenchmarkProcess(b *testing.B) {
data := setupTestData()
b.ResetTimer()
for i := 0; i < b.N; i++ {
process(data)
}
}
func BenchmarkProcessParallel(b *testing.B) {
data := setupTestData()
b.ResetTimer()
b.RunParallel(func(pb *testing.PB) {
for pb.Next() {
process(data)
}
})
}
测试模式
表驱动测试
func TestAdd(t *testing.T) {
tests := []struct {
name string
a, b int
expected int
}{
{"positive", 2, 3, 5},
{"negative", -1, -2, -3},
{"zero", 0, 0, 0},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
result := Add(tt.a, tt.b)
if result != tt.expected {
t.Errorf("Add(%d, %d) = %d; want %d",
tt.a, tt.b, result, tt.expected)
}
})
}
}
向用户展示结果
提供 Go 解决方案时:
- 使用符合 Go 惯例的模式
- 始终显式处理错误
- 包含 context 传递
- 提供测试示例
- 注明 Go 版本要求(泛型:1.18+)
故障排除
“检测到数据竞争”
- 使用
go test -race查找竞争 - 使用互斥锁保护共享状态
- 考虑使用 channel 进行通信
“Goroutine 泄漏”
- 确保已关闭 channel
- 使用 context 取消操作
- 检查是否存在阻塞操作
“内存使用量过高”
- 使用 pprof 进行性能分析
- 检查 slice 容量问题
- 检查 map 是否不断累积
评论
支持 Markdown