【golang-技巧】- context 使用
1.context是什么?
context.Context 是 Go 语言标准库中的一个类型,用于在多个 Goroutine 之间传递请求的上下文,以及控制请求的生命周期。Context 类型提供了一种机制,可以让程序在一个请求或操作被取消或超时时,及时释放资源或退出。以下是 context.Context 的作用、应用场景、最佳实践和代码实例。
context.Context 的主要作用是传递请求的上下文信息,并控制请求的生命周期。它可以用来传递请求的元数据、请求 ID、用户信息等,在多个 Goroutine 之间进行传递和访问。同时,Context 还可以用于控制请求的超时和取消,以及通知 Goroutine 关闭资源和退出程序。
Context 类型的应用场景比较广泛,包括但不限于以下几个方面:
Web 服务器:在 Web 服务器中,每个请求都可以创建一个 Context 对象,用于存储请求的元数据、用户信息等,并控制请求的生命周期和取消。
RPC 通信:在 RPC 通信中,可以使用 Context 对象传递请求的上下文信息,并控制请求的超时和取消。
数据库访问:在访问数据库时,可以使用 Context 对象传递数据库连接信息,并控制请求的超时和取消。
日志记录:在记录日志时,可以使用 Context 对象传递请求的元数据和用户信息等,方便后续查询和分析。
以下是一些使用 context.Context 的最佳实践:
传递 Context 对象时,应该显式传递,而不是通过全局变量或函数参数等方式传递。
在请求处理过程中,应该根据需要进行 Context 对象的传递和修改,以确保每个请求都有独立的 Context 对象。
在创建 Context 对象时,应该尽量设置超时和取消机制,以避免资源泄漏和程序挂起。
代码实例:
2.example
timeout
func TestExceedTime(t *testing.T) {
ctx, cancel := context.WithTimeout(context.Background(), time.Second*5)
defer cancel()
go func(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("context has cancel or timeout")
return
default:
fmt.Println("process request")
time.Sleep(time.Second)
}
}
}(ctx)
time.Sleep(time.Second * 10)
}
在上面的代码中,我们首先创建了一个带有超时和取消机制的 Context 对象 ctx,并传递给一个 Goroutine。在 Goroutine 中,我们模拟了一个耗时的操作,并使用 select 语句不断判断 Context 对象的状态,如果已经超时或取消,则退出 Goroutine。在主程序中,我们等待请求处理完成,然后退出程序。如果在 5 秒内请求处理完成,则输出“request processed successfully”;否则,输出“request canceled or timeout”。这个例子展示了如何使用 context.Context 进行超时和取消控制,避免 Goroutine 资源泄漏和程序挂起。
value
func TestCtxValue(t *testing.T) {
ctx := context.WithValue(context.Background(), "name", "haha")
name := ctx.Value("name")
fmt.Println("name", name)
ctx = context.WithValue(context.Background(), "name", "lala")
name = ctx.Value("name")
fmt.Println("name", name)
}
cancel
func TestCtxCancel(t *testing.T) {
ctx, cancel := context.WithCancel(context.Background())
go func(ctx context.Context) {
time.Sleep(time.Second * 5)
cancel()
}(ctx)
for {
select {
case <-ctx.Done():
fmt.Println("ctx has cancel")
os.Exit(-1)
default:
fmt.Println("has running")
time.Sleep(time.Second)
}
}
}