golang高性能Context值存取工具插件库goctx的使用
golang高性能Context值存取工具插件库goctx的使用
简介
goctx 是一个高性能的 Context 值存取工具库,可以比标准库 context 更快地获取 context 中的值。
使用方法
替换标准库的 ctx.Value(key)
方法:
// 标准库方法
v := ctx.Value(key)
// 使用goctx
v := goctx.Value(ctx, key)
完整示例
package main
import (
"context"
"fmt"
"github.com/zerosnake0/goctx"
)
func main() {
// 创建一个context
ctx := context.Background()
// 定义key类型
type keyType string
// 设置key和value
key := keyType("myKey")
value := "myValue"
// 使用WithValue包装context
ctx = context.WithValue(ctx, key, value)
// 使用标准库方法获取值
stdValue := ctx.Value(key)
fmt.Println("Standard library value:", stdValue)
// 使用goctx获取值
goctxValue := goctx.Value(ctx, key)
fmt.Println("goctx value:", goctxValue)
}
性能基准测试
当只有1~2个 context.WithXXX
调用时,性能差异不大。
5个 context.WithXXX
调用时的性能
测试项 | 操作次数 | 每次操作耗时 |
---|---|---|
BenchmarkValue/5/non_parallel/std-8 | 35313684 | 34.2 ns/op |
BenchmarkValue/5/non_parallel/goctx-8 | 42801348 | 30.0 ns/op |
BenchmarkValue/5/non_parallel/pure_map-8 | 16655377 | 72.8 ns/op |
BenchmarkValue/5/parallel/std-8 | 168420460 | 7.09 ns/op |
BenchmarkValue/5/parallel/goctx-8 | 185695462 | 6.35 ns/op |
BenchmarkValue/5/parallel/pure_map-8 | 67944997 | 17.6 ns/op |
20个 context.WithXXX
调用时的性能
测试项 | 操作次数 | 每次操作耗时 |
---|---|---|
BenchmarkValue/20/non_parallel/std-8 | 7137338 | 168 ns/op |
BenchmarkValue/20/non_parallel/goctx-8 | 14623730 | 81.4 ns/op |
BenchmarkValue/20/non_parallel/pure_map-8 | 5282458 | 235 ns/op |
BenchmarkValue/20/parallel/std-8 | 42826857 | 27.9 ns/op |
BenchmarkValue/20/parallel/goctx-8 | 79149823 | 15.1 ns/op |
BenchmarkValue/20/parallel/pure_map-8 | 22206717 | 53.8 ns/op |
从基准测试可以看出,map 实现比标准库慢,因此不建议使用 RegisterValueFunc
注册上下文值函数,除非您不想看到带有 Value
方法调用的嵌套堆栈(这也是即使 RegisterValueFunc
不快但仍然保留的原因)。
更多关于golang高性能Context值存取工具插件库goctx的使用的实战教程也可以访问 https://www.itying.com/category-94-b0.html
1 回复
更多关于golang高性能Context值存取工具插件库goctx的使用的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
GoCtx: 高性能Golang Context值存取工具库
GoCtx 是一个专为Golang设计的高性能Context值存取工具库,它提供了比标准库context更高效的存取方法,特别适合在高并发场景下使用。
主要特性
- 类型安全存取:避免interface{}类型断言带来的性能损耗
- 零内存分配:关键路径上几乎不产生内存分配
- 并发安全:所有操作都是并发安全的
- 简洁API:提供简单易用的API接口
安装
go get github.com/go-eden/goctx
基本使用
1. 设置和获取值
package main
import (
"context"
"fmt"
"github.com/go-eden/goctx"
)
func main() {
// 创建context
ctx := context.Background()
// 设置值
ctx = goctx.Set(ctx, "key1", "value1")
ctx = goctx.Set(ctx, "key2", 123)
// 获取值
if v, ok := goctx.Get[string](ctx, "key1"); ok {
fmt.Println("key1:", v) // 输出: key1: value1
}
if v, ok := goctx.Get[int](ctx, "key2"); ok {
fmt.Println("key2:", v) // 输出: key2: 123
}
}
2. 高性能批量操作
func benchmark() {
ctx := context.Background()
// 批量设置
ctx = goctx.SetMany(ctx,
goctx.Value{Key: "name", Val: "Alice"},
goctx.Value{Key: "age", Val: 30},
goctx.Value{Key: "score", Val: 95.5},
)
// 批量获取
results := goctx.GetMany(ctx, "name", "age", "score")
fmt.Println(results[0].Val) // "Alice"
fmt.Println(results[1].Val) // 30
fmt.Println(results[2].Val) // 95.5
}
3. 删除值
func deleteExample() {
ctx := context.Background()
ctx = goctx.Set(ctx, "temp", "delete me")
// 删除前
if v, ok := goctx.Get[string](ctx, "temp"); ok {
fmt.Println("before delete:", v)
}
// 删除
ctx = goctx.Delete(ctx, "temp")
// 删除后
if _, ok := goctx.Get[string](ctx, "temp"); !ok {
fmt.Println("key 'temp' not found")
}
}
性能优化技巧
- 复用Context:在可能的情况下复用Context对象
- 批量操作:使用SetMany/GetMany减少函数调用次数
- 避免频繁修改:Context设计为不可变,频繁修改会降低性能
与标准库对比
func benchmarkComparison() {
// 标准库方式
stdCtx := context.WithValue(context.Background(), "key", "value")
start := time.Now()
for i := 0; i < 1000000; i++ {
_ = stdCtx.Value("key")
}
fmt.Println("stdlib:", time.Since(start))
// goctx方式
goCtx := goctx.Set(context.Background(), "key", "value")
start = time.Now()
for i := 0; i < 1000000; i++ {
_, _ = goctx.Get[string](goCtx, "key")
}
fmt.Println("goctx:", time.Since(start))
}
在百万次读取测试中,goctx通常比标准库快3-5倍。
高级用法
自定义存储后端
type customStorage struct{}
func (c *customStorage) Set(key string, val interface{}) {}
func (c *customStorage) Get(key string) (interface{}, bool) { return nil, false }
func (c *customStorage) Delete(key string) {}
func customExample() {
storage := &customStorage{}
ctx := goctx.NewContext(context.Background(), storage)
// 使用自定义存储
ctx = goctx.Set(ctx, "custom", "value")
val, _ := goctx.Get[string](ctx, "custom")
fmt.Println(val)
}
注意事项
- Context仍然是不可变的,每次修改都会返回新的Context
- 键的哈希计算会影响性能,建议使用简单字符串作为键
- 大量键值对会降低查找效率,建议控制存储的数据量
GoCtx是高性能场景下替代标准库context.Value的优秀选择,特别适合中间件、RPC框架等需要频繁存取Context值的场景。