Context 理解今天学习 Go 代码时遇到一个常用的包Context这是 Go 语言中用于管理一次任务或一次请求生命周期的标准库通常用于在多个函数调用之间传递取消信号、超时信息以及请求级数据。如何理解这个 context 的作用呢以服务器接收用户请求为例首先我们要知道一个稍微复杂一些的系统在服务器收到请求后不是只有一个简单的函数调用的而是涉及到一系列工具的调用链这个调用链需要知道当前请求是否仍然有效例如用户是否已经取消请求、连接是否已经断开、是否已经超时等。如果没有统一的通知机制各个组件就需要自行设计取消逻辑代码会变得复杂而且容易出现资源浪费。Context 提供了一种统一的通知机制。当调用 cancel() 或请求超时后所有共享该 Context 并监听 ctx.Done() 的 goroutine 都会收到取消信号从而及时停止当前工作。context 作为参数伴随着一个请求从开始到结束沿着整个调用链一直传递。所有参与处理这个请求的函数、数据库操作、RPC 调用、后台 goroutine 都共享同一个 Context。这样当请求取消、用户断开连接、超时或服务需要关闭时只需要发出一次通知整个调用链上的所有组件都能知道这个请求已经结束不要再继续工作了。同样的道理除了取消通知之外context还支持超时控制Timeout、截止时间Deadline以及请求级数据Value的传递。常用 Context 用法下面就几个常用 Context 的最简单应用代码了解一下使用方法1. WithCancel —— 主动取消package main import ( context fmt time ) func main() { // 创建一个可取消的 Context ctx, cancel : context.WithCancel(context.Background()) // 启动后台任务 go func() { for { select { case -ctx.Done(): fmt.Println(收到取消通知退出任务) return default: fmt.Println(正在工作...) time.Sleep(time.Second) } } }() time.Sleep(3 * time.Second) // 主动取消 cancel() time.Sleep(time.Second) }输出如下正在工作... 正在工作... 正在工作... 收到取消通知退出任务2. WithTimeout —— 超时自动取消package main import ( context fmt time ) func main() { // 设置 3 秒超时 ctx, cancel : context.WithTimeout(context.Background(), 3*time.Second) defer cancel() -ctx.Done() fmt.Println(任务结束, ctx.Err()) }输出如下任务结束 context deadline exceeded3. WithDeadline —— 指定截止时间package main import ( context fmt time ) func main() { deadline : time.Now().Add(5 * time.Second) ctx, cancel : context.WithDeadline(context.Background(), deadline) defer cancel() -ctx.Done() fmt.Println(到达截止时间, ctx.Err()) }输出如下到达截止时间 context deadline exceeded4. WithValue —— 传递请求数据package main import ( context fmt ) func main() { ctx : context.WithValue(context.Background(), requestID, req-1001) handle(ctx) } func handle(ctx context.Context) { id : ctx.Value(requestID) fmt.Println(当前请求ID, id) }输出如下当前请求ID req-1001补充另外需要注意的是Context 是可以一层层派生的。context.Background() 相当于创建了一个什么都没有的白纸 context 再由以上的函数一层层“叠buff”增加能力ctx : context.Background() // 空 Context ctx, cancel : context.WithCancel(ctx) // 增加取消能力 ctx context.WithValue(ctx, user, Tom) // 再增加请求级数据 ctx, cancel2 : context.WithTimeout(ctx, 5*time.Second) // 再增加超时初学 Go 代码先写这些内容未来学了更多会继续补充。
Go 常用包 Context 基础理解与使用
Context 理解今天学习 Go 代码时遇到一个常用的包Context这是 Go 语言中用于管理一次任务或一次请求生命周期的标准库通常用于在多个函数调用之间传递取消信号、超时信息以及请求级数据。如何理解这个 context 的作用呢以服务器接收用户请求为例首先我们要知道一个稍微复杂一些的系统在服务器收到请求后不是只有一个简单的函数调用的而是涉及到一系列工具的调用链这个调用链需要知道当前请求是否仍然有效例如用户是否已经取消请求、连接是否已经断开、是否已经超时等。如果没有统一的通知机制各个组件就需要自行设计取消逻辑代码会变得复杂而且容易出现资源浪费。Context 提供了一种统一的通知机制。当调用 cancel() 或请求超时后所有共享该 Context 并监听 ctx.Done() 的 goroutine 都会收到取消信号从而及时停止当前工作。context 作为参数伴随着一个请求从开始到结束沿着整个调用链一直传递。所有参与处理这个请求的函数、数据库操作、RPC 调用、后台 goroutine 都共享同一个 Context。这样当请求取消、用户断开连接、超时或服务需要关闭时只需要发出一次通知整个调用链上的所有组件都能知道这个请求已经结束不要再继续工作了。同样的道理除了取消通知之外context还支持超时控制Timeout、截止时间Deadline以及请求级数据Value的传递。常用 Context 用法下面就几个常用 Context 的最简单应用代码了解一下使用方法1. WithCancel —— 主动取消package main import ( context fmt time ) func main() { // 创建一个可取消的 Context ctx, cancel : context.WithCancel(context.Background()) // 启动后台任务 go func() { for { select { case -ctx.Done(): fmt.Println(收到取消通知退出任务) return default: fmt.Println(正在工作...) time.Sleep(time.Second) } } }() time.Sleep(3 * time.Second) // 主动取消 cancel() time.Sleep(time.Second) }输出如下正在工作... 正在工作... 正在工作... 收到取消通知退出任务2. WithTimeout —— 超时自动取消package main import ( context fmt time ) func main() { // 设置 3 秒超时 ctx, cancel : context.WithTimeout(context.Background(), 3*time.Second) defer cancel() -ctx.Done() fmt.Println(任务结束, ctx.Err()) }输出如下任务结束 context deadline exceeded3. WithDeadline —— 指定截止时间package main import ( context fmt time ) func main() { deadline : time.Now().Add(5 * time.Second) ctx, cancel : context.WithDeadline(context.Background(), deadline) defer cancel() -ctx.Done() fmt.Println(到达截止时间, ctx.Err()) }输出如下到达截止时间 context deadline exceeded4. WithValue —— 传递请求数据package main import ( context fmt ) func main() { ctx : context.WithValue(context.Background(), requestID, req-1001) handle(ctx) } func handle(ctx context.Context) { id : ctx.Value(requestID) fmt.Println(当前请求ID, id) }输出如下当前请求ID req-1001补充另外需要注意的是Context 是可以一层层派生的。context.Background() 相当于创建了一个什么都没有的白纸 context 再由以上的函数一层层“叠buff”增加能力ctx : context.Background() // 空 Context ctx, cancel : context.WithCancel(ctx) // 增加取消能力 ctx context.WithValue(ctx, user, Tom) // 再增加请求级数据 ctx, cancel2 : context.WithTimeout(ctx, 5*time.Second) // 再增加超时初学 Go 代码先写这些内容未来学了更多会继续补充。