电子商务网站建设的心得,网站外包哪家公司好,手机网站建设价格明细表,15年做哪个网站致富0 概述
Context 是 Go 语言中非常重要的一个概念#xff0c;它主要用于跨多个函数或 goroutine 传递 取消信号、超时控制、截止时间 和 请求范围数据。在并发编程中#xff0c;Context 提供了更好的控制和管理#xff0c;尤其是当你需要在多个 goroutine 之间传递状态或进行…0 概述
Context 是 Go 语言中非常重要的一个概念它主要用于跨多个函数或 goroutine 传递 取消信号、超时控制、截止时间 和 请求范围数据。在并发编程中Context 提供了更好的控制和管理尤其是当你需要在多个 goroutine 之间传递状态或进行资源清理时。
1 主要功能
Context 主要有以下几个功能
取消信号通知一个或多个 goroutine 取消它们正在执行的工作。超时和截止时间指定操作的最大执行时间防止阻塞操作过长时间。传递请求范围数据携带请求范围内的数据通常用于请求 ID、用户信息等。
2 Context 的三种基本类型
Go 中的 context 包提供了几种常用的 Context 类型
context.Background()通常作为根 Context表示没有附加数据或取消信号的上下文。它通常是根上下文作为其他上下文的父上下文。context.TODO()表示你暂时没有确定使用什么样的 Context通常用于占位。context.WithCancel(parent)创建一个可取消的 Context并返回一个取消函数当你调用这个函数时Context 会被取消。context.WithTimeout(parent, timeout)创建一个带有超时的 Context指定最大等待时间超过这个时间会自动取消。context.WithDeadline(parent, deadline)指定一个具体的截止时间超过这个时间后自动取消。context.WithValue(parent, key, value)创建一个携带键值对数据的 Context通常用于传递请求级别的数据例如用户身份信息。
3 常见用法举例
3.1 context.WithCancel传递取消信号
主要场景
手动控制并发任务的终止。优雅退出在一个任务中途需要取消时用 cancel() 通知所有相关的 goroutine 停止执行。
代码示例
package mainimport (contextfmttime
)func main() {// 创建一个可取消的 Contextctx, cancel : context.WithCancel(context.Background())// 启动一个 goroutine监听取消信号go func(ctx context.Context) {for {select {case -ctx.Done(): // 检测到取消信号fmt.Println(Goroutine stopped)returndefault:// 模拟工作fmt.Println(Working...)time.Sleep(1 * time.Second)}}}(ctx)// 主线程等待 3 秒后取消time.Sleep(3 * time.Second)cancel() // 发送取消信号// 等待 goroutine 退出time.Sleep(1 * time.Second)fmt.Println(Main program exited)
}解释
主线程创建了一个带有取消功能的上下文 ctx。子 goroutine 使用 ctx.Done() 监听取消信号。主线程 3 秒后调用 cancel()子 goroutine 检测到信号后优雅退出。
3.2 使用 WithTimeout 设置超时
context.WithTimeout 用于设置一个超时时间超过该时间后 Context 会自动取消适用于需要限时执行的操作。防止某些任务阻塞的时间过长。
package mainimport (contextfmttime
)func main() {// 设置超时时间为 2 秒ctx, cancel : context.WithTimeout(context.Background(), 2*time.Second)defer cancel() // 确保超时后取消 ctx// 启动一个模拟长时间执行的任务go longRunningTask(ctx)// 等待超时或任务完成-ctx.Done()if ctx.Err() context.DeadlineExceeded {fmt.Println(Timeout reached)}
}func longRunningTask(ctx context.Context) {select {case -time.After(3 * time.Second): // 模拟长时间任务fmt.Println(Task completed)case -ctx.Done():// 任务被取消或超时fmt.Println(Task cancelled due to timeout)}
}WithDeadline 的用法和Withtimeout用法类似只是一个传入的参数是等待时间一个传入的参数是截止时间。
3.3 使用 WithValue 传递数据
context.WithValue 可以在 Context 中存储键值对通常用于传递请求级别的数据例如用户身份、请求 ID 等。
package mainimport (contextfmt
)func main() {// 创建一个上下文并传递数据ctx : context.WithValue(context.Background(), userID, 12345)// 将 ctx 传递给其他函数processRequest(ctx)
}func processRequest(ctx context.Context) {// 从 ctx 中提取数据userID : ctx.Value(userID)if userID ! nil {fmt.Println(User ID:, userID)} else {fmt.Println(No user ID found)}
}使用 WithValue 小心context.WithValue 并不是用于传递大量数据的主要用于传递少量的上下文信息比如请求 ID 等。如果传递过多的数据会使得 Context 难以维护。
4 常用的相关方法和常量
ctx.Done()返回一个 channel当 Context 被取消时该 channel 会被关闭。ctx.Err()返回 Context 被取消的错误通常是 context.Canceled 或 context.DeadlineExceeded。ctx.Value(key)获取在 Context 中传递的数据。
5 context如何控制goroutine的执行
从上面的举例可以看出在每个goroutine中通过判断ctx.Done()是否被执行从而知道任务是否被取消/超时/到达截止日期。
当 Context 被取消调用 cancel()或超时/到达截止时间时ctx.Done() 所关联的 channel 会关闭此时select语句就可以执行ctx.Done()对应的分支。