Files
OpenFlare/.agents/skills/go-concurrency/references/GOROUTINE-PATTERNS.md
T
2026-08-04 11:40:32 +08:00

2.7 KiB
Raw Blame History

Goroutine 生命周期模式

管理 goroutine 生命周期的详细模式 —— 确保每个 goroutine 都有清晰的启动/停止机制并防止资源泄漏。


使生命周期清晰

WaitGroup 示例和作用域规则在父 skill(SKILL.md § Goroutine 生命周期,核心规则)中。本参考涵盖:stop/done channel 模式、等待策略、init() 生命周期示例和同步 API 设计。


Stop/Done Channel 模式

每个 goroutine 必须有可预测的停止机制。使用 stop channel 通知关闭,使用 done channel 确认退出:

var (
    stop = make(chan struct{}) // 通知 goroutine 停止
    done = make(chan struct{}) // 通知我们 goroutine 已退出
)
go func() {
    defer close(done)
    ticker := time.NewTicker(delay)
    defer ticker.Stop()
    for {
        select {
        case <-ticker.C:
            flush()
        case <-stop:
            return
        }
    }
}()

// 关闭时:
close(stop)  // 通知 goroutine 停止
<-done       // 并等待它退出

在已关闭的 channel 上发送会 panic —— 始终使用 close() 来发信号,不要直接发送:

ch := make(chan int)
close(ch)
ch <- 13 // panic: 在已关闭的 channel 上发送

等待 Goroutine

多 goroutine 的 sync.WaitGroup 模式在父 skill 中(SKILL.md § Goroutine 生命周期)。以下是单 goroutine 的 done-channel 替代方案。

为单个 goroutine 使用 done channel:

done := make(chan struct{})
go func() {
    defer close(done)
    // 工作...
}()
<-done // 等待 goroutine 完成

不在 init() 中使用 Goroutine

核心规则在父 skill 中(SKILL.md § 核心规则,规则 3)。以下是展示生命周期管理的扩展示例。

// 不好:创建了不可控的后台 goroutine
func init() {
    go doWork()
}
// 好:显式的生命周期管理
type Worker struct {
    stop chan struct{}
    done chan struct{}
}

func NewWorker() *Worker {
    w := &Worker{
        stop: make(chan struct{}),
        done: make(chan struct{}),
    }
    go w.doWork()
    return w
}

func (w *Worker) Shutdown() {
    close(w.stop)
    <-w.done
}

优先使用同步函数

理由和优势表在父 skill 中(SKILL.md § 同步函数)。以下是具体的代码示例。

// 好:同步函数 - 调用方控制并发
func ProcessItems(items []Item) ([]Result, error) {
    var results []Result
    for _, item := range items {
        result, err := processItem(item)
        if err != nil {
            return nil, err
        }
        results = append(results, result)
    }
    return results, nil
}

// 调用方可以在需要时添加并发:
go func() {
    results, err := ProcessItems(items)
    // 处理结果
}()