mirror of
https://github.com/Rain-kl/OpenFlare.git
synced 2026-09-28 05:46:36 +08:00
127 lines
2.7 KiB
Markdown
127 lines
2.7 KiB
Markdown
# Goroutine 生命周期模式
|
||
|
||
管理 goroutine 生命周期的详细模式 —— 确保每个 goroutine 都有清晰的启动/停止机制并防止资源泄漏。
|
||
|
||
---
|
||
|
||
## 使生命周期清晰
|
||
|
||
> WaitGroup 示例和作用域规则在父 skill(SKILL.md § Goroutine 生命周期,核心规则)中。本参考涵盖:stop/done channel 模式、等待策略、init() 生命周期示例和同步 API 设计。
|
||
|
||
---
|
||
|
||
## Stop/Done Channel 模式
|
||
|
||
每个 goroutine 必须有可预测的停止机制。使用 stop channel 通知关闭,使用 done channel 确认退出:
|
||
|
||
```go
|
||
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()` 来发信号,不要直接发送:
|
||
|
||
```go
|
||
ch := make(chan int)
|
||
close(ch)
|
||
ch <- 13 // panic: 在已关闭的 channel 上发送
|
||
```
|
||
|
||
---
|
||
|
||
## 等待 Goroutine
|
||
|
||
> 多 goroutine 的 `sync.WaitGroup` 模式在父 skill 中(SKILL.md § Goroutine 生命周期)。以下是单 goroutine 的 done-channel 替代方案。
|
||
|
||
为单个 goroutine 使用 done channel:
|
||
|
||
```go
|
||
done := make(chan struct{})
|
||
go func() {
|
||
defer close(done)
|
||
// 工作...
|
||
}()
|
||
<-done // 等待 goroutine 完成
|
||
```
|
||
|
||
---
|
||
|
||
## 不在 init() 中使用 Goroutine
|
||
|
||
> 核心规则在父 skill 中(SKILL.md § 核心规则,规则 3)。以下是展示生命周期管理的扩展示例。
|
||
|
||
```go
|
||
// 不好:创建了不可控的后台 goroutine
|
||
func init() {
|
||
go doWork()
|
||
}
|
||
```
|
||
|
||
```go
|
||
// 好:显式的生命周期管理
|
||
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 § 同步函数)。以下是具体的代码示例。
|
||
|
||
```go
|
||
// 好:同步函数 - 调用方控制并发
|
||
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)
|
||
// 处理结果
|
||
}()
|
||
```
|