golang多种退出模式
golang多种退出模式
1. 基于 channel 的退出模式
通过共享的 channel 发送退出信号,其他 goroutine 监听该信号并决定何时退出。
示例:
package main
import (
"fmt"
"time"
)
func worker(id int, quit chan bool) {
for {
select {
case <-quit:
fmt.Printf("Worker %d: exiting\n", id)
return
default:
fmt.Printf("Worker %d: working\n", id)
time.Sleep(time.Second)
}
}
}
func main() {
quit := make(chan bool)
// 启动多个 worker goroutines
for i := 1; i <= 3; i++ {
go worker(i, quit)
}
// 主 goroutine 等待一段时间后发送退出信号
time.Sleep(5 * time.Second)
close(quit) // 发送退出信号,所有 worker 会收到并退出
// 等待一段时间,确保所有 worker 都退出
time.Sleep(1 * time.Second)
}
在此示例中,主 goroutine 在 5 秒后关闭 quit 通道,通知所有 worker goroutine 退出。
2. 基于 context 的退出模式
使用 context 来管理 goroutine 的生命周期,支持超时和取消操作。
示例:
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context, id int) {
for {
select {
case <-ctx.Done():
fmt.Printf("Worker %d: exiting, reason: %v\n", id, ctx.Err())
return
default:
fmt.Printf("Worker %d: working\n", id)
time.Sleep(time.Second)
}
}
}
func main() {
// 创建一个可以取消的 context
ctx, cancel := context.WithCancel(context.Background())
defer cancel() // 确保超时后 cancel 被调用
// 启动多个 worker goroutines
for i := 1; i <= 3; i++ {
go worker(ctx, i)
}
// 主 goroutine 等待一段时间后取消 context
time.Sleep(5 * time.Second)
cancel() // 取消 context,所有 worker 会收到退出信号
// 等待一段时间,确保所有 worker 都退出
time.Sleep(1 * time.Second)
}
在此示例中,主 goroutine 在 5 秒后调用 cancel(),通知所有 worker goroutine 退出。
3. 基于超时的退出模式
使用 context.WithTimeout 设置超时时间,超时后自动取消上下文,适用于需要在一定时间内完成任务的场景。
示例:
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context, id int) {
for {
select {
case <-ctx.Done():
fmt.Printf("Worker %d: exiting due to timeout, reason: %v\n", id, ctx.Err())
return
default:
fmt.Printf("Worker %d: working\n", id)
time.Sleep(time.Second)
}
}
}
func main() {
// 创建一个带超时的 context,设置超时时间为 3 秒
ctx, cancel := context.WithTimeout(context.Background(), 3*time.Second)
defer cancel() // 确保超时后 cancel 被调用
// 启动多个 worker goroutines
for i := 1; i <= 3; i++ {
go worker(ctx, i)
}
// 等待超时,所有 worker 会自动收到退出信号
time.Sleep(5 * time.Second)
}
在此示例中,主 goroutine 创建了一个 3 秒后自动取消的上下文,所有 worker goroutine 会在超时后自动退出。
4. 基于 sync.WaitGroup 的退出模式
使用 sync.WaitGroup 等待一组 goroutine 执行完毕,确保所有 goroutine 完成后再退出主程序。
示例:
package main
import (
"fmt"
"sync"
"time"
)
func worker(id int, wg *sync.WaitGroup) {
defer wg.Done() // 当 goroutine 完成时调用 Done()
for i := 0; i < 3; i++ {
fmt.Printf("Worker %d: working\n", id)
time.Sleep(time.Second)
}
fmt.Printf("Worker %d: done\n", id)
}
func main() {
var wg sync.WaitGroup
// 启动多个 worker goroutines
for i := 1; i <= 3; i++ {
wg.Add(1) // 为每个 goroutine 增加计数
go worker(i, &wg)
}
// 等待所有 worker 完成
wg.Wait()
fmt.Println("All workers finished.")
}
在此示例中,主 goroutine 使用 sync.WaitGroup 等待所有 worker goroutine 完成后再退出。5. 基于 defer 的退出模式在 goroutine 中使用 defer 语句来确保在退出时执行清理操作。
示例:
package main
import (
"fmt"
"time"
)
func worker(id int) {
defer fmt.Printf("Worker %d: done\n", id) // 当 goroutine 退出时执行
for i := 0; i < 3; i++ {
fmt.Printf("Worker %d: working\n", id)
time.Sleep(time.Second)
}
}
func main() {
// 启动多个 worker goroutines
for i := 1; i <= 3; i++ {
go worker(i)
}
// 等待一段时间,确保所有 worker 完成
time.Sleep(5 * time.Second)
}
在此示例中,defer 确保每个 worker goroutine 在退出时打印 "done" 信息。
总结
- 基于
channel的退出模式 :通过共享的channel发送退出信号,其他 goroutine 监听该信号并退出。 - 基于
context的退出模式 :使用context管理 goroutine 的生命周期,支持超时和取消操作。 - 基于超时的退出模式 :使用
context.WithTimeout设置超时时间,超时后自动取消上下文,适用于需要在一定时间内完成任务的场景。 - 基于
sync.WaitGroup的退出模式 :使用sync.WaitGroup等待一组 goroutine 执行完毕,确保所有 goroutine 完成后再退出主程序。 - 基于
defer的退出模式 :在 goroutine 中使用defer语句来确保在退出时执行清理操作。

浙公网安备 33010602011771号