面试题答案
一键面试在Go语言中,context
包主要用于在多个goroutine
之间传递截止时间、取消信号以及其他请求域的值。以下是使用context
包实现通知退出机制,确保并发程序优雅关停的详细步骤和代码示例:
- 创建一个
context
对象:一般使用context.Background()
作为根context
,然后基于它衍生出带有取消功能的context
。 - 传递
context
到各个goroutine
:每个需要监听退出信号的goroutine
都应该接受这个context
。 - 在
goroutine
中监听取消信号:使用context
的Done()
通道来监听取消信号,一旦接收到信号,就停止当前goroutine
的工作。 - 发送取消信号:在主程序中,当需要退出时,调用取消函数来发送取消信号。
以下是具体的代码示例:
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context, id int) {
for {
select {
case <-ctx.Done():
// 当接收到取消信号时,退出循环
fmt.Printf("Worker %d stopped\n", id)
return
default:
// 模拟工作
fmt.Printf("Worker %d is working\n", id)
time.Sleep(1 * time.Second)
}
}
}
func main() {
// 创建一个可取消的context
ctx, cancel := context.WithCancel(context.Background())
// 启动多个goroutine
numWorkers := 3
for i := 1; i <= numWorkers; i++ {
go worker(ctx, i)
}
// 模拟主程序工作一段时间
time.Sleep(3 * time.Second)
// 发送取消信号
cancel()
// 等待所有goroutine退出
time.Sleep(2 * time.Second)
fmt.Println("All workers stopped, program exiting")
}
代码解释
-
worker
函数:- 接受一个
context.Context
类型的参数ctx
和一个表示worker
编号的id
。 - 在
for
循环中,使用select
语句监听ctx.Done()
通道。当ctx.Done()
通道接收到数据时,说明取消信号已发出,worker
打印停止信息并返回,结束goroutine
。 - 在
default
分支中,模拟worker
的工作,每秒打印一次工作信息。
- 接受一个
-
main
函数:- 使用
context.WithCancel(context.Background())
创建一个可取消的context
,并返回ctx
和cancel
函数。ctx
用于传递取消信号到各个goroutine
,cancel
函数用于手动发送取消信号。 - 启动多个
worker
goroutine
,并传递ctx
。 - 主程序休眠3秒模拟工作,之后调用
cancel()
函数发送取消信号。 - 再休眠2秒,确保所有
goroutine
有足够时间接收到取消信号并退出,最后打印程序退出信息。
- 使用