golang 提高反射性能

    golang的反射很慢,这个和它的api设计有关。

type_ := reflect.ValueOf(obj)
fieldValue := type_.FieldByName("hello")

   这里取出来的fielValue类型是reflect.Value,它是一个具体的值,而不是一个可复用的反射对象。这样每次反射都需要malloc这个reflect.Value结构体。

   Jsoniter是golang是实现的,基于反射的JSON解析器。其实原理是用reflect.Type得出来的信息来直接做反射。而不依赖于reflect.ValueOf。

 

具体做法

结构体

   1.利用refect.StructField取得对象上的值,对应的代码在: go/feature_reflect_object.go at master · json-iterator/go · GitHub:

fieldPtr := uintptr(structPtr) + field.Offset

   在reflect.StructField上有一个Offset的属性。利用这个可以计算出字段的指针值。测试示例:

type TestObj struct {
	field1 string
}
struct_ := &TestObj{}
field, _ := reflect.TypeOf(struct_).Elem().FieldByName("field1")
field1Ptr := uintptr(unsafe.Pointer(struct_)) + field.Offset
*((*string)(unsafe.Pointer(field1Ptr))) = "hello"
fmt.Println(struct_)

   打印出来的消息是&{hello}

  2.获取interface{}的指针

    如果对应的结构体是以interface{}传进来的。还需要从interface{}上取得结构体的指针

type TestObj struct {
	field1 string
}
struct_ := &TestObj{}
structInter := (interface{})(struct_)
// emptyInterface is the header for an interface{} value.
type emptyInterface struct {
	typ  *struct{}
	word unsafe.Pointer
}
structPtr := (*emptyInterface)(unsafe.Pointer(&structInter)).word
field, _ := reflect.TypeOf(structInter).Elem().FieldByName("field1")
field1Ptr := uintptr(structPtr) + field.Offset
*((*string)(unsafe.Pointer(field1Ptr))) = "hello"
fmt.Println(struct_)


slice类型

   对应的代码在:go/feature_reflect_array.go at master · json-iterator/go · GitHub

type sliceHeader struct {
	Data unsafe.Pointer
	Len  int
	Cap  int
}

   slice的秘密在于取出指向数组头部的指针,然后具体的元素,通过偏移量来计算。

slice := []string{"hello", "world"}
type sliceHeader struct {
	Data unsafe.Pointer
	Len  int
	Cap  int
}
header := (*sliceHeader)(unsafe.Pointer(&slice))
fmt.Println(header.Len)
elementType := reflect.TypeOf(slice).Elem()
secondElementPtr := uintptr(header.Data) + elementType.Size()
*((*string)(unsafe.Pointer(secondElementPtr))) = "!!!"
fmt.Println(slice)

   打印出来的内容:

2
[hello !!!]
Map

  对于Map类型来说,没有reflect.ValueOf之外的获取其内容的方式。所以只能老老实实地用golang自带的值反射api。

 

参考:

https://www.yuque.com/docs/share/e78ab6c1-3a7f-4311-bb3d-bc99a55753dc

你可能感兴趣的:(Go)