You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
But the FieldByName() and Index() method are design for the reflection interface "type Value". And the costs are not necessary in this case.
I wrote two methods for that:
// StructFieldByName returns the struct field with the given name.// It returns the nil if no field was found.// It panics if input data Kind is not struct.funcStructFieldByName(structDatainterface{}, namestring) interface{} {
// unpack Structe:= (*emptyInterface)(unsafe.Pointer(&structData))
startPointer:=e.word// check flagvalueMetadataFlag:=e.typ.kindifvalueMetadataFlag==0 {
panic("invalied reflect.Value.Type")
}
// please input a struct type data ifvalueMetadataFlag!=structKind {
panic("Field of non-struct type ")
}
// pick up target fieldvartargetStructField*structFieldtt:= (*structType)(unsafe.Pointer(e.typ))
fori:=rangett.fields {
tf:=&tt.fields[i]
iftf.name.name() ==name {
targetStructField=tf
}
}
iftargetStructField==nil {
returnnil
}
// repack target fieldvarpackedinterface{}
pe:= (*emptyInterface)(unsafe.Pointer(&packed))
pe.typ=targetStructField.typpe.word=add(startPointer, targetStructField.offset(), "same as non-reflect &v.field")
returnpacked
}
// Get all elements from an interface (slice type)// SliceAllElements returns the all elements from an interface (slice type).// It returns the nil if no field was found.// It panics if input data Kind is not slice.funcSliceAllElements(sliceDatainterface{}) []interface{} {
// unpack Structe:= (*emptyInterface)(unsafe.Pointer(&sliceData))
// check flagvalueMetadataFlag:=e.typ.kindifvalueMetadataFlag==0 {
panic("invalied reflect.Value.Type")
}
// please input a slice type data ifvalueMetadataFlag!=sliceKind {
panic("non-slice type ")
}
s:= (*UnsafeSlice)(e.word)
// check slice len and init a container for return ifs.Len<1 { // an empty slicereturnnil
}
// pickup and returnallElements:=make([]interface{}, s.Len)
tt:= (*sliceType)(unsafe.Pointer(e.typ))
typ:=tt.elemfori:=0; i<s.Len; i++ {
element:=arrayAt(s.Data, i, typ.size, "i < s.Len")
varpackedinterface{}
pe:= (*emptyInterface)(unsafe.Pointer(&packed))
pe.typ=typpe.word=elementallElements[i] =packed
}
returnallElements
}
I expect that the field lookup will be faster if you first decide which field names you are going to look up, use reflect.Type.FieldByName to fetch the reflect.StructField, save the Index value, and then every time you want to look up the field value use reflect.Value.FieldByIndex. Or in the normal case that the fields are not embedded so the length of the Index value is 1, use reflect.Value.Field.
Your all-elements code will be faster if you don't call v.Len on each loop iteration. But it will probably still be slower than your unsafe code.
I think it's unlkely that we will support unpacking the reflect package in the ways that you suggest. That will make it impossible to ever change the reflection data structures.
I'm writing a GraphQL implementation by Go, In some case, I need to get field by name from a struct:
e.g.
or get all elements from a slice:
e.g.
But the FieldByName() and Index() method are design for the reflection interface "type Value". And the costs are not necessary in this case.
I wrote two methods for that:
And the benchmark result are:
But these methods depend on the private method from the reflect lib. and if the lib changed, these methods will crash.
So can we do some performance improvements like this, Or maybe there's a fast way to do this already?
Thanks.
The text was updated successfully, but these errors were encountered: