Golang Context包使用教程
Golang Context包使用教程 Go语言中的context包用于在API边界之间传递请求范围的值、取消信号和截止时间。它可以用来存储元数据、取消信号、超时以及其他请求范围的值。context包提供了一种取消长时间运行操作的方式,以及跨API边界存储元数据的方法。它通常与http包一起使用,以管理HTTP请求的请求范围值和取消信号。
1 回复
更多关于Golang Context包使用教程的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
在Go语言中,context包是处理请求生命周期和跨API边界传递元数据的核心工具。它主要用于管理取消信号、超时和请求范围的值。以下是一个详细的使用示例,涵盖基本创建、超时设置、值传递和取消操作。
1. 创建基础Context
使用context.Background()或context.TODO()创建根Context,通常作为请求的起点。
package main
import (
"context"
"fmt"
"time"
)
func main() {
// 创建根Context
ctx := context.Background()
processRequest(ctx)
}
func processRequest(ctx context.Context) {
// 模拟处理请求
fmt.Println("处理请求中...")
}
2. 设置超时和截止时间
使用context.WithTimeout或context.WithDeadline设置超时,自动触发取消。
func main() {
ctx := context.Background()
// 设置2秒超时
ctx, cancel := context.WithTimeout(ctx, 2*time.Second)
defer cancel()
go handleTask(ctx)
time.Sleep(3 * time.Second) // 模拟主程序等待
}
func handleTask(ctx context.Context) {
select {
case <-time.After(3 * time.Second):
fmt.Println("任务完成")
case <-ctx.Done():
fmt.Println("任务取消:", ctx.Err()) // 输出: context deadline exceeded
}
}
3. 传递请求范围的值
使用context.WithValue存储和检索请求范围的元数据。
func main() {
ctx := context.Background()
// 存储用户ID
ctx = context.WithValue(ctx, "userID", "12345")
authUser(ctx)
}
func authUser(ctx context.Context) {
// 检索值
if userID := ctx.Value("userID"); userID != nil {
fmt.Println("用户ID:", userID) // 输出: 用户ID: 12345
}
}
4. 手动取消操作
使用context.WithCancel创建可手动取消的Context,适用于需要主动终止的场景。
func main() {
ctx, cancel := context.WithCancel(context.Background())
go performOperation(ctx)
time.Sleep(1 * time.Second)
cancel() // 手动取消操作
time.Sleep(500 * time.Millisecond)
}
func performOperation(ctx context.Context) {
for {
select {
case <-ctx.Done():
fmt.Println("操作终止:", ctx.Err()) // 输出: context canceled
return
default:
fmt.Println("操作执行中...")
time.Sleep(200 * time.Millisecond)
}
}
}
5. 在HTTP请求中的应用
结合http包管理请求生命周期,例如设置服务器端超时。
package main
import (
"context"
"net/http"
"time"
)
func main() {
http.HandleFunc("/api", apiHandler)
http.ListenAndServe(":8080", nil)
}
func apiHandler(w http.ResponseWriter, r *http.Request) {
// 为请求创建带超时的Context
ctx, cancel := context.WithTimeout(r.Context(), 1*time.Second)
defer cancel()
// 将Context传递给处理函数
result := make(chan string)
go fetchData(ctx, result)
select {
case data := <-result:
w.Write([]byte("数据: " + data))
case <-ctx.Done():
http.Error(w, "请求超时", http.StatusGatewayTimeout)
}
}
func fetchData(ctx context.Context, result chan<- string) {
// 模拟耗时操作
time.Sleep(2 * time.Second)
result <- "完成"
}
关键点总结
- 取消传播:Context取消信号会向下传递到所有派生Context。
- 线程安全:Context是并发安全的,可在多个goroutine中使用。
- 值传递限制:仅存储请求范围的数据,避免滥用。
- 错误处理:始终检查
ctx.Done()和ctx.Err()以处理取消或超时。
这些示例覆盖了Context包的核心用法,可直接用于实际开发中管理goroutine生命周期和请求元数据。

