mcpField
G
golang-master

golang-master

github.com/tomlord1122开发047 次安装6 周前更新
代码仓库

关于 golang-master

面向 Go 开发者的编程技能,涵盖惯用设计、并发、错误处理、测试与性能分析,并附带代码检查和基准测试脚本。

主要功能

  1. 01Go 问题分类
  2. 02惯用设计指导
  3. 03并发模式
  4. 04错误处理策略
  5. 05测试与性能分析指导
  6. 06代码检查和基准测试脚本

适用场景

  1. 01设计 goroutine 协作方式
  2. 02追踪并包装错误
  3. 03规划表驱动测试
  4. 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+)
  • 模块结构是什么样的?(标准布局还是扁平结构)
  • 有哪些依赖?(标准库还是第三方库)
  • 是否有需要遵循的现有模式?(错误处理风格、日志记录方式)

操作:

  1. 检查 go.mod 中的 Go 版本和依赖
  2. 扫描现有代码,了解既定模式
  3. 识别任何特定于项目的约定
第 3 步:解决方案设计(符合 Go 惯用方式)

目标: 设计符合 Go 最佳实践的解决方案。

思考框架——应用以下原则:

  1. 简单优先

    • “有没有更简单的实现方式?”
    • 避免过度设计;Go 倾向于明确表达
  2. 错误处理

    • “这里可能发生什么错误?应该如何传递错误?”
    • 使用 fmt.Errorf("context: %w", err) 包装错误
    • 为特定领域的错误定义自定义错误类型
  3. 并发安全

    • “是否有多个 goroutine 访问此数据?”
    • “我需要互斥锁、通道还是原子操作?”
    • 优先使用通道进行协调,使用互斥锁保护状态
  4. 接口设计

    • “需要什么行为,而不是需要什么数据?”
    • 保持接口精简(1–3 个方法)
    • 接受接口,返回具体类型
  5. 资源管理

    • “哪些资源需要关闭或清理?”
    • 使用 defer 进行清理
    • 传递 context 以支持取消操作
第 4 步:应用模式进行实现

目标: 恰当地应用常见的 Go 模式。

模式选择指南:

问题类型推荐模式
并发处理 N 个项目Worker Pool
限制并发操作数量Semaphore
为长时间运行的操作设置超时带 Deadline 的 Context
协调多个 goroutineWaitGroup
扇出/扇入处理通道流水线
优雅关闭Context 取消 + 信号处理

决策点: 对于每种模式,思考:

  • “为什么这种模式适用于这个问题?”
  • “我需要处理哪些边缘情况?”
第 5 步:测试策略

目标: 确保代码正确且易于维护。

思考框架:

  • “有哪些正常流程需要测试?”
  • “哪些边缘情况可能导致问题?”
  • “这段代码是否便于测试?如果不便于,我应该如何重构?”

测试清单:

  1. 对具有多种输入场景的函数使用表驱动测试
  2. 对并发代码进行竞态检测(go test -race)
  3. 对性能关键代码进行基准测试
  4. 为外部依赖模拟接口
步骤 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