在 Golang 中,可以使用 context.Context 来控制 Goroutine 的生命周期和取消。具体做法是,在启动 Goroutine 时,将一个 context.Context 对象传递给 Goroutine,在 Goroutine 内部使用 select 语句监听 context.Context.Done() 通道,如果该通道被关闭,则表示需要关闭 Goroutine。示例如下:
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
// 收到关闭信号,退出循环
return
default:
// 执行任务
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
// 启动 Goroutine
go worker(ctx)
// 等待一定时间后关闭 Goroutine
time.AfterFunc(time.Second * 5, func() {
cancel()
})
// 等待 Goroutine 退出
time.Sleep(time.Second * 10)
}
下面再来看一个使用 Context
来优雅地关闭 Goroutine 的示例代码:
golang www.itzhimei.com代码
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("worker: context cancelled, exiting...")
return
default:
fmt.Println("worker: doing work...")
time.Sleep(1 * time.Second)
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
go worker(ctx)
// 等待 5 秒后取消 Context
time.Sleep(5 * time.Second)
cancel()
// 等待 worker goroutine 退出
<-ctx.Done()
fmt.Println("main: worker exited.")
}
在上面的代码中,我们首先使用 context.WithCancel
函数创建了一个携带取消信号的 Context
,并将其传递给 worker
函数。在 worker
函数中,我们使用 select
语句来检查 Context
是否被取消,如果被取消,则立即退出。
在 main
函数中,我们等待 5 秒后调用 cancel
函数来取消 Context
,此时 worker
函数中的 Context.Done()
通道会被关闭,worker
函数会收到取消信号并退出。
最后,我们使用 <-ctx.Done()
来等待 worker
函数退出,确保所有的 Goroutine 都已经结束。
这样,我们就可以优雅地关闭 Goroutine,避免资源泄露和其他潜在的问题。