plugins/languages/golang/skills/concurrency/SKILL.md
Go 并发规范——go.uber.org/atomic 原子操作(非 sync/atomic)、errgroup 并发编排(SetLimit 限流)、context 超时取消传播、sync.Pool 对象复用、WaitGroup.Go(Go 1.25+)、Go 1.23 iter 迭代器、Green Tea GC(Go 1.26 默认)。写 goroutine、设计并发流程、调查竞态/泄漏、性能调优时触发。
npx skillsauth add lazygophers/ccplugin golang-concurrencyInstall this skill globally with one command. Works with Claude Code, Cursor, and Windsurf.
3 of 9 scanners reported clean
Some scanners were skipped, did not run, or reported a non-clean status. Review each row below.
go.uber.org/atomic,禁直接 sync/atomic。go func()。errgroup,必须 SetLimit 限制并发。sync.Pool 复用。import "go.uber.org/atomic"
counter := atomic.NewInt64(0)
counter.Inc()
counter.Add(10)
val := counter.Load()
flag := atomic.NewBool(false)
flag.Toggle()
flag.Store(true)
name := atomic.NewString("")
name.Store("hello")
类型安全 + API 友好,比标准库 sync/atomic 少 50% 出错。
var bufferPool = sync.Pool{
New: func() any { return new(bytes.Buffer) },
}
func processData(data []byte) string {
buf := bufferPool.Get().(*bytes.Buffer)
defer bufferPool.Put(buf)
buf.Reset()
buf.Write(data)
return buf.String()
}
适用:每秒上千次创建-销毁的临时对象(buffer、struct)。低频对象不要 Pool,反而增加复杂度。
import "golang.org/x/sync/errgroup"
eg, ctx := errgroup.WithContext(ctx)
eg.SetLimit(10) // 必设并发上限
for _, item := range items {
eg.Go(func() error {
return process(ctx, item)
})
}
err = eg.Wait()
if err != nil {
log.Errorf("err:%v", err)
return err
}
注:Go 1.22+ 循环变量自动每轮新建,无需 item := item。
简单场景,不需要错误传播:
var wg sync.WaitGroup
for _, item := range items {
wg.Go(func() { // 自动 Add(1) + defer Done()
process(item)
})
}
wg.Wait()
需错误传播 → 用 errgroup。仅扇出无错误 → WaitGroup.Go。
// 超时
ctx, cancel := context.WithTimeout(ctx, 5*time.Second)
defer cancel()
// 取消
ctx, cancel := context.WithCancel(ctx)
defer cancel()
// 传播 + 协作取消
func processItem(ctx context.Context, item *Item) error {
select {
case <-ctx.Done():
return ctx.Err()
default:
}
// 长操作中循环检查
for chunk := range item.Chunks() {
select {
case <-ctx.Done():
return ctx.Err()
default:
handle(chunk)
}
}
return nil
}
每个 goroutine 入口函数第一个参数必须是 ctx context.Context,整链路传到底。
import (
"iter"
"maps"
"slices"
)
for k, v := range maps.All(m) { fmt.Println(k, v) }
for i, v := range slices.All(s) { fmt.Println(i, v) }
func FilterIter[T any](seq iter.Seq[T], fn func(T) bool) iter.Seq[T] {
return func(yield func(T) bool) {
for v := range seq {
if fn(v) && !yield(v) { return }
}
}
}
适合流式/惰性场景;急切批处理仍用 candy。
result := make([]string, 0, len(items))
for _, item := range items {
result = append(result, item.String())
}
import "github.com/lazygophers/log"
buf := log.GetBuffer()
defer log.PutBuffer(buf)
GOEXPERIMENT=nogreenteagc 编译。GOEXPERIMENT=goroutineleakprofile go build .
# 运行后访问 /debug/pprof/goroutineleak
零开销,1.27 拟默认开启。
golang-testing)testing/synctest(Go 1.25 GA)+ -race 是标配:
go test -race ./...
| AI 借口 | 实际应验证 | | --- | --- | | "sync/atomic 是标准库" | 用 go.uber.org/atomic? | | "mutex 更简单" | 简单计数用 atomic? | | "goroutine 很轻量" | 有 errgroup + context 控制? | | "context 到处传麻烦" | 入口函数都接 ctx? | | "不需要 SetLimit" | errgroup 设上限? | | "iter 太新" | 适用场景用了? |
go.uber.org/atomicsync.Poolerrgroup + SetLimit-racetesting/synctestdevelopment
Go 数据库规范——GORM Model 命名 ModelXxx、表名单数、枚举 uint8 + 常量、索引 idx_ 前缀 + deleted_at leading column、禁 time.Time 统一 int64 unix、禁指针/nullable 字段、TEXT/BLOB/JSON 禁 default、AutoMigrate 禁改主键。设计 DB model、写 GORM tag、建索引、做 migration 审查时触发。
development
Go HTTP API 规范——响应始终 200 + body code 字段、路由 /api/* 全 POST 单段 <Action><Model>、中间件逐路由注册禁 Group(prefix,mw...)、handler 仅返回 (rsp,error)、认证走 header。设计 HTTP API、写路由/handler/中间件时触发。
development
Go 项目结构规范——三层架构(API → Impl → State)、全局状态模式、internal/ 私有包、cmd/ 仅 main.go、go.work 多模块、禁止 Repository 接口和 DI 容器、struct 公共字段开头全 omitempty、handler var rsp 顶声明、禁 legacy migration。设计项目骨架、新建目录、组织包、做架构评审时触发。
development
Go 命名规范——Id/Uid 字段(非 ID)、IsActive/HasMFA 布尔前缀、CreatedAt 时间字段、接收者统一用 p、包名全小写无下划线、泛型类型参数描述性命名、集合字段 xxx_list 禁 xxxs 复数、Enum 0 值 XxxNil 禁 Unknown、禁 Status 统一 State、Set/Update 语义区分。定义结构体字段、函数、变量、包、接收者名、泛型、枚举时触发。