方案原理
- 反射预热:在程序启动阶段,通过反射获取基础类型的结构体字段信息,并缓存起来。这样在高并发读写时,避免每次都进行反射操作获取信息,从而减少反射带来的性能开销。
- 类型断言:在读取和修改数据时,利用类型断言将接口类型转换为实际的基础类型,直接操作数据,提升性能。
实现步骤
- 初始化缓存:
var typeInfoCache = make(map[reflect.Type]map[string]reflect.Value)
func init() {
// 假设存在结构体类型
type TestStruct struct {
IntValue int
FloatValue float64
}
t := reflect.TypeOf(TestStruct{})
info := make(map[string]reflect.Value)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
info[field.Name] = reflect.ValueOf(&TestStruct{}).Elem().FieldByName(field.Name)
}
typeInfoCache[t] = info
}
- 读取和修改操作:
func GetValue(obj interface{}, fieldName string) interface{} {
t := reflect.TypeOf(obj)
info, ok := typeInfoCache[t]
if!ok {
// 处理未缓存的情况,重新构建缓存
info = make(map[string]reflect.Value)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
info[field.Name] = reflect.ValueOf(obj).Elem().FieldByName(field.Name)
}
typeInfoCache[t] = info
}
value, ok := info[fieldName]
if!ok {
return nil
}
return value.Interface()
}
func SetValue(obj interface{}, fieldName string, value interface{}) {
t := reflect.TypeOf(obj)
info, ok := typeInfoCache[t]
if!ok {
// 处理未缓存的情况,重新构建缓存
info = make(map[string]reflect.Value)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
info[field.Name] = reflect.ValueOf(obj).Elem().FieldByName(field.Name)
}
typeInfoCache[t] = info
}
target, ok := info[fieldName]
if!ok {
return
}
target.Set(reflect.ValueOf(value))
}
- 高并发调用:
func main() {
var wg sync.WaitGroup
testObj := &TestStruct{}
for i := 0; i < 100; i++ {
wg.Add(1)
go func() {
defer wg.Done()
SetValue(testObj, "IntValue", i)
val := GetValue(testObj, "IntValue")
fmt.Println(val)
}()
}
wg.Wait()
}
性能测试对比
- 编写测试用例:
package main
import (
"testing"
)
func BenchmarkDirectReflection(b *testing.B) {
testObj := &TestStruct{}
for n := 0; n < b.N; n++ {
v := reflect.ValueOf(testObj).Elem().FieldByName("IntValue")
v.SetInt(int64(n))
_ = v.Int()
}
}
func BenchmarkOptimizedReflection(b *testing.B) {
testObj := &TestStruct{}
for n := 0; n < b.N; n++ {
SetValue(testObj, "IntValue", n)
_ = GetValue(testObj, "IntValue")
}
}
- 执行测试:
在命令行中执行
go test -bench=.
,会输出两种方式的性能对比结果,通过对比 BenchmarkDirectReflection
和 BenchmarkOptimizedReflection
的结果,可以直观看到优化方案的性能提升情况。例如,如果 BenchmarkOptimizedReflection
的每秒操作次数(ops)明显高于 BenchmarkDirectReflection
,则说明优化方案有效。