This is a creation in Article, where the information may have evolved or changed. The reflection of the Golang is very slow. This is related to its API design. In Java, we usually use reflection to do this.
Fieldfield=clazz.getField("hello");field.get(obj1);field.get(obj2);
The type of reflection object obtained is Java.lang.reflect.Field. It can be reused. As long as the different obj is passed in, the corresponding field on this obj can be obtained. But Golang's reflection is not designed like this.
type_ := reflect.TypeOf(obj)field, _ := type_.FieldByName("hello")
The Field object to be taken out here is reflect. The Structfield type, but it has no way to get the value on the corresponding object. If you want to take a value, you have to use a different set of reflections on object instead of type.
type_ := reflect.ValueOf(obj)fieldValue := type_.FieldByName("hello")
The Fieldvalue type that is taken out here is reflect. Value, which is a concrete value, not a reusable reflection object.
It's a pain in the egg! the reflect of malloc is required for each reflection. The value struct body. How can Golang's reflective performance be fast?
The Jsoniter is a Golang-based JSON parser that is implemented by reflection. Its implementation principle is to use reflect. Type the information to be reflected directly, without relying on reflect. ValueOf. How is it implemented?
Structural body
Solve a small problem first. How to use reflect. Structfield gets the value on the object?
The corresponding code is in: Go/feature_reflect_object.go at Master Json-iterator/go GitHub
fieldPtr := uintptr(structPtr) + field.Offset
in reflect. There is an Offset property on the Structfield. Use this to calculate the pointer value of a field. We can write a small test to verify that this is the right one.
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_)
The printed message is &{hello}
Get Pointer to interface{}
If the corresponding struct is passed in as interface{}. You also need to get a pointer to the struct from interface{}
type Testobj struct {field1 string}struct_ := &Testobj{}Structinter := (Interface{})(struct_)//Emptyinterface is the header for a interface{} value.type Emptyinterface struct {Typ *struct{}Word unsafe.Pointer}structptr := (*Emptyinterface)(unsafe.Pointer(&Structinter)).WordField, _ := reflect.TypeOf(Structinter).Elem().Fieldbyname("Field1")field1ptr := UIntPtr(structptr) + Field.Offset*((*string)(unsafe.Pointer(field1ptr))) = "Hello"FMT.Println(struct_)
Slice
The structure is done, and then the slice type is processed.
The corresponding code is in: Go/feature_reflect_array.go at Master Json-iterator/go GitHub
type sliceHeader struct {Data unsafe.PointerLen intCap int}
The secret of slice is to remove the pointer to the head of the array, and then the specific element, calculated by the offset.
Slice := []string{"Hello", "World"}type Sliceheader struct {Data unsafe.PointerLen intCap 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)
Print out the content
2[hello!!!]
Map
There is no reflect for the Map type. How to get their content outside of ValueOf. So you can only honestly use the value of Golang to reflect the API.