面试题答案
一键面试-
使用
context
管理goroutine
取消操作及传递截止时间信息的原理:context
包提供了一种优雅的方式来管理goroutine
的生命周期。context.Context
类型被设计为携带截止时间、取消信号及其他请求范围的值,这些值可以在goroutine
树中传递。context.WithCancel
函数用于创建一个可取消的context
,调用返回的取消函数可以取消这个context
,所有基于这个context
派生的子context
也会被取消。context.WithTimeout
函数用于创建一个带有超时的context
,在指定的时间后会自动取消,也可以通过调用返回的取消函数提前取消。
-
代码示例:
package main
import (
"context"
"fmt"
"time"
)
// 模拟从数据库读取数据的函数
func readDataFromDB(ctx context.Context) error {
// 模拟一个长时间运行的任务
select {
case <-time.After(5 * time.Second):
// 这里模拟数据库读取操作完成
return nil
case <-ctx.Done():
// 如果context被取消,返回取消错误
return ctx.Err()
}
}
func main() {
// 创建一个带有2秒超时的context
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel() // 确保函数结束时取消context,释放资源
err := readDataFromDB(ctx)
if err != nil {
fmt.Printf("操作被取消或超时: %v\n", err)
} else {
fmt.Println("数据读取成功")
}
}
在上述代码中:
context.WithTimeout(context.Background(), 2*time.Second)
创建了一个带有2秒超时的context
。readDataFromDB
函数内部使用select
语句监听time.After(5 * time.Second)
(模拟数据库读取操作完成)和ctx.Done()
(context
被取消的信号)。- 如果
context
在数据库读取操作完成前被取消(这里是超时取消),ctx.Done()
通道会收到信号,函数返回取消错误。如果数据库读取操作在context
取消前完成,函数返回nil
。