mcpField
G
go-ops

go-ops

github.com/0xdarkmatter开发7851 次安装2 周前更新
代码仓库

关于 go-ops

面向 Go 开发的参考技能,涵盖惯用写法、并发、测试、项目结构和性能,为开发者提供速查内容与专题资料。

主要功能

  1. 01惯用 Go 写法与错误处理
  2. 02并发模式与指导
  3. 03接口与泛型
  4. 04测试与项目结构
  5. 05性能分析与优化实践

适用场景

  1. 01选择错误处理方式
  2. 02设计并发 Go 任务
  3. 03规划 Go 项目包结构
  4. 04测试或分析 Go 项目性能

安装

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

$npx skills add https://github.com/0xdarkmatter/claude-mods --skill go-ops

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

包含的文件

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

assets/
.gitkeep
references/
concurrency.md
error-handling.md
expert-insights.md
interfaces-generics.md
performance.md
project-structure.md
testing.md
scripts/
.gitkeep

详细介绍

Go 运维

全面的 Go 技能,涵盖惯用模式、并发和生产实践。

模块快速入门

# New module
go mod init github.com/user/project

# Add dependency
go get github.com/lib/pq@latest

# Tidy (remove unused, add missing)
go mod tidy

# Vendor dependencies
go mod vendor

# Workspace (multi-module)
go work init ./api ./shared
go work use ./cli

错误处理决策树

What kind of error?
│
├─ Known, expected condition (e.g. "not found")
│  └─ Sentinel error: var ErrNotFound = errors.New("not found")
│     └─ Caller checks: errors.Is(err, ErrNotFound)
│
├─ Need to carry structured data (status code, field name)
│  └─ Custom error type: type ValidationError struct { Field, Message string }
│     └─ Implement Error() string
│     └─ Caller checks: errors.As(err, &validErr)
│
├─ Adding context to an existing error
│  └─ Wrap: fmt.Errorf("load config: %w", err)
│     └─ Preserves original for Is/As checks
│
├─ Truly unrecoverable (corrupted state, programmer bug)
│  └─ panic("invariant violated: ...")
│     └─ Almost never in library code
│
└─ Multiple errors from concurrent work
   └─ errors.Join(err1, err2) or multierr package
错误包装约定
// Add context at each layer, don't repeat the function name
func LoadUser(id int) (*User, error) {
    row, err := db.Query("SELECT ...", id)
    if err != nil {
        return nil, fmt.Errorf("load user %d: %w", id, err)
    }
    // ...
}

并发决策树

What's the concurrency pattern?
│
├─ Run N independent tasks, collect results
│  └─ errgroup.Group (cancels on first error)
│
├─ Fire-and-forget background work
│  └─ go func() with context for cancellation
│     └─ ALWAYS handle the error or log it
│
├─ Producer/consumer pipeline
│  └─ Channels (buffered for throughput)
│     └─ Close channel when producer is done
│
├─ Rate-limited concurrent work
│  └─ Semaphore: make(chan struct{}, maxConcurrency)
│
├─ Shared mutable state
│  └─ sync.Mutex or sync.RWMutex
│     └─ Prefer channels if the state is simple
│
├─ One-time initialization
│  └─ sync.Once
│
└─ Wait for N goroutines to finish (no error collection)
   └─ sync.WaitGroup
errgroup 快速入门
import "golang.org/x/sync/errgroup"

g, ctx := errgroup.WithContext(ctx)
g.SetLimit(10) // max 10 concurrent goroutines

for _, url := range urls {
    g.Go(func() error {
        return fetch(ctx, url)
    })
}

if err := g.Wait(); err != nil {
    return fmt.Errorf("fetch urls: %w", err)
}

深入了解:加载 ./references/concurrency.md,了解工作池、扇出/扇入、流水线模式和 context 最佳实践。

接口设计

Accept interfaces, return structs.
// Good: function accepts interface
func Process(r io.Reader) error { ... }

// Good: return concrete type
func NewServer(cfg Config) *Server { ... }

// Bad: returning interface (hides implementation, prevents extension)
func NewServer(cfg Config) ServerInterface { ... }
常见标准库接口
接口方法用途
io.ReaderRead([]byte) (int, error)任意字节源
io.WriterWrite([]byte) (int, error)任意字节接收端
io.CloserClose() error资源清理
fmt.StringerString() string字符串表示
errorError() string错误值
sort.InterfaceLen, Less, Swap自定义排序
http.HandlerServeHTTP(w, r)HTTP 处理器
encoding.BinaryMarshalerMarshalBinary() ([]byte, error)二进制编码
函数式选项模式
type Option func(*Server)

func WithPort(port int) Option {
    return func(s *Server) { s.port = port }
}

func WithTimeout(d time.Duration) Option {
    return func(s *Server) { s.timeout = d }
}

func NewServer(opts ...Option) *Server {
    s := &Server{port: 8080, timeout: 30 * time.Second} // defaults
    for _, opt := range opts {
        opt(s)
    }
    return s
}

// Usage
srv := NewServer(WithPort(9090), WithTimeout(5*time.Second))

深入了解:加载 ./references/interfaces-generics.md,了解泛型、类型约束、嵌入和类型断言。

测试快速参考

// Table-driven test
func TestAdd(t *testing.T) {
    tests := []struct {
        name     string
        a, b     int
        expected int
    }{
        {"positive", 1, 2, 3},
        {"zero", 0, 0, 0},
        {"negative", -1, -2, -3},
    }
    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            got := Add(tt.a, tt.b)
            if got != tt.expected {
                t.Errorf("Add(%d, %d) = %d, want %d", tt.a, tt.b, got, tt.expected)
            }
        })
    }
}
# Run tests
go test ./...

# With coverage
go test -cover -coverprofile=coverage.out ./...
go tool cover -html=coverage.out

# Run specific test
go test -run TestAdd ./pkg/math/

# Benchmarks
go test -bench=. -benchmem ./...

# Race detector
go test -race ./...

# Fuzz testing
go test -fuzz=FuzzParse ./...

深入了解:加载 ./references/testing.md,了解使用接口进行模拟、httptest、testcontainers 和黄金文件。

常见陷阱

陷阱原因修复方法
nil 切片与空切片var s []int 为 nil,s := []int{} 为空。json.Marshal 分别生成 null 和 []如果 JSON 结果很重要,请使用 make([]int, 0) 或 []int{}
Goroutine 泄漏Goroutine 阻塞在没有读写方的通道上使用 context.WithCancel,始终提供退出路径
循环中的 defer延迟调用要等函数返回后才会执行将循环体包装在闭包中,或使用显式清理
接口 nil 陷阱将 (*MyType)(nil) 赋给 error 接口后,它不等于 nil显式返回 nil,不要返回类型化的 nil 指针
Range 变量捕获循环变量会被重复使用(Go 1.22 之前)使用 go func(v T) { ... }(v),或升级到 Go 1.22+
循环中进行字符串拼接O(n^2) 次分配使用 strings.Builder
在 Go 之后调用 sync.WaitGroup 的 Add竞态条件在 go func() 之前调用 wg.Add(1)
无缓冲通道死锁发送和接收必须并发发生使用带缓冲的通道或独立的 Goroutine
map 不支持并发安全使用竞态条件,可能崩溃使用 sync.Mutex 或 sync.Map

项目结构

project/
├── cmd/
│   ├── api/main.go           # Entry points
│   └── worker/main.go
├── internal/                  # Private packages
│   ├── handler/
│   ├── service/
│   └── repository/
├── pkg/                       # Public packages (optional)
├── go.mod
├── go.sum
├── Makefile                   # or justfile
└── .golangci.yml

深入了解:加载 ./references/project-structure.md,了解工作区模式、构建标签、ldflags 和 lint 配置。

性能快速参考

# CPU profile
go test -cpuprofile=cpu.prof -bench=. ./...
go tool pprof cpu.prof

# Memory profile
go test -memprofile=mem.prof -bench=. ./...
go tool pprof -alloc_space mem.prof

# Trace
go test -trace=trace.out ./...
go tool trace trace.out

# Escape analysis
go build -gcflags='-m' ./...
优化适用场景模式
预分配切片大小已知make([]T, 0, n)
strings.Builder字符串拼接var b strings.Builder
sync.Pool频繁分配和释放同一类型pool.Get() / pool.Put()
结构体字段对齐对内存敏感按大小分组字段(从大到小)
缓冲区复用I/O 密集型bufio.NewReaderSize(r, 64*1024)

深入了解:加载 ./references/performance.md,了解 pprof 使用指南、基准测试模式和逃逸分析。

参考文件

深入了解相关主题时,请加载这些文件。每个文件均可独立使用。

参考文件加载时机
./references/concurrency.mdGoroutine、通道、上下文、同步原语、工作池、流水线
./references/error-handling.md错误包装、哨兵错误、自定义类型、多错误、panic/recover
./references/testing.md表驱动测试、模拟、httptest、基准测试、模糊测试、testcontainers、黄金文件
./references/interfaces-generics.md接口设计、嵌入、类型断言、泛型、类型约束
./references/project-structure.md标准目录布局、go.mod、工作区、构建标签、ldflags、golangci-lint
./references/performance.mdpprof、trace、基准测试、逃逸分析、sync.Pool、结构体对齐
./references/expert-insights.mdHTTP 服务端(Go 1.22 路由)、优雅关闭、http.Client 调优、JSON 辅助函数

另请参阅

  • docker-ops - Go 二进制文件的多阶段构建(scratch/distroless)
  • ci-cd-ops - Go CI 流水线、缓存 Go 模块、goreleaser
  • testing-ops - 跨语言测试策略

评论

支持 Markdown