面试题答案
一键面试Go上下文在调度方面的最基本作用
- 控制生命周期:可以通过上下文来取消或超时控制一组相关的goroutine,避免资源浪费和内存泄漏。比如一个HTTP请求启动了多个goroutine来处理不同的任务,当请求取消时,相关goroutine也能及时停止。
- 传递截止时间:能够设置一个截止时间,让所有基于该上下文衍生的操作在截止时间前完成,若超时则可以进行相应处理。例如数据库查询操作,设置一个截止时间,避免长时间等待。
- 传递请求范围的数据:在不同的goroutine之间传递请求特定的数据,比如认证信息、请求ID等,便于在整个请求处理过程中使用。
利用上下文控制goroutine的生命周期示例
package main
import (
"context"
"fmt"
"time"
)
func worker(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("收到取消信号,退出goroutine")
return
default:
fmt.Println("工作中...")
time.Sleep(1 * time.Second)
}
}
}
func main() {
ctx, cancel := context.WithCancel(context.Background())
go worker(ctx)
time.Sleep(3 * time.Second)
cancel()
time.Sleep(1 * time.Second)
fmt.Println("程序结束")
}
在上述代码中,context.WithCancel
创建了一个可取消的上下文 ctx
以及取消函数 cancel
。worker
goroutine 中通过 ctx.Done()
监听取消信号,当主函数在3秒后调用 cancel
时,worker
goroutine 接收到取消信号并退出,从而控制了 worker
goroutine 的生命周期。