go通过context.WithValue传递指针
文章目录
Go - Context: 信息穿透上下文
使用场景
- 上下文传递信息(request-scoped),比如处理http请求、在请求处理链路上传递信息;
- 控制子goroutine的运行;
- 超时控制的方法调用(timeout);
- 可以取消的方法调用(cancel);
WithValue-传递上下文
以下是传递上下文方式
ctx = context.TODO()
ctx = context.WithValue(ctx, "key1", "0001")
ctx = context.WithValue(ctx, "key2", "0001")
ctx = context.WithValue(ctx, "key3", "0001")
ctx = context.WithValue(ctx, "key4", "0004")
fmt.Println(ctx.Value("key1"))
WithValue-通过透传指针参数(ctx.Value的值需要变化)
context通过透传指针参数可便于函数内外部修改与接收
应用场景: (ctx.Value的值需要变化)
- 外部修改ctx.Value的值: 内部可以获取参数的值改变(比如需提前cancel并需改变某个透传的值)
- 内部修改ctx.Value的值: 外部可以获取参数的值改变(内部执行到某位置并修改了透传的值)
示例
package main
import (
"context"
"fmt"
"time"
)
// golang-context通过透传指针参数可便于函数内外部修改与接收
// 应用场景: (ctx.Value的值需要变化)
// 外部修改ctx.Value的值: 内部可以获取参数的值改变(比如需提前cancel并需改变某个透传的值)
// 内部修改ctx.Value的值: 外部可以获取参数的值改变(内部执行到某位置并修改了透传的值)
func main() {
// 初始cancel context
ctx, cancel := context.WithCancel(context.Background())
// 预先设置传递参数
params := make([]string, 0)
results := make([]any, 0)
ctx = context.WithValue(ctx, "params", ¶ms) // 指针,调用内修改,外部直接使用其值
ctx = context.WithValue(ctx, "results", &results) // 指针,外部直接修改,调用内获取值
// 手动触发cancel
go func() {
time.Sleep(1 * time.Second)
// 这时ctx.Value("params")已被函数内修改,newParams和params一致
fmt.Println("params", params)
newParams := ctx.Value("params").(*[]string)
fmt.Println("newParams", newParams)
// 直接修改results,这时ctx.Value("results")已修改
results = []any{"1", "2", "3"}
fmt.Println("results", results)
// 调用cancel,提前结束testContextValue
cancel()
}()
// 执行
newResults := testContextValue(ctx, 20*time.Second)
// 结果 &["1", "2", "3"]
fmt.Println("newResults", newResults)
}
// 应用场景
func testContextValue(ctx context.Context, timeout time.Duration) (resp *[]any) {
// code before ...
// 测试修改Context参数值
oldIds, ok := ctx.Value("params").(*[]string)
if ok {
*(oldIds) = []string{"a", "b", "c"}
}
// 阻塞或提前cancel
select {
case <-ctx.Done(): // 主动cancel
// 主动调用cancelFunc前可先更改context参数值,
// 主动停止时设置响应结果,通过context接收数据
resp, _ = ctx.Value("results").(*[]any)
case <-time.After(timeout): // 阻塞
}
// after code ...
return
}