[英]go reflection: get correct struct type of interface
Consider this: 考虑一下:
type myStruct struct {
Foo string `json:"foo"`
}
func main() {
somelibrary.DoThing(func(thing myStruct) {
// myStruct should contain unmarshaled JSON
// provided by somelibrary
fmt.Printf("%v\n", thing)
})
}
I'm new to Go, so I fear this might not be idiomatic code. 我是Go的新手,所以我担心这可能不是惯用的代码。 I'd like to implement somelibrary.DoThing
so it correctly infers the struct type from the function argument via reflection, if it's possible. 我想实现somelibrary.DoThing
以便通过反射正确地从函数参数中推断出结构类型,如果可能的话。 Here's what I have: 这就是我所拥有的:
const jsonData := []byte{`{"foo": "bar"}`}
func DoThing(fn interface{}) {
// Get first arg of the function
firstArg := reflect.TypeOf(fn).In(0)
structPtr := reflect.New(firstArg)
// Convert to Interface
// Note that I can't assert this to .(myStruct) type
instance := structPtr.Elem().Interface()
// Unmarshal the JSON
json.Unmarshal(jsonData, &instance)
// Call the function
vfn := reflect.ValueOf(fn)
vfn.Call([]reflect.Value{reflect.ValueOf(instance)})
}
Without knowing the struct type beforehand, json.Unmarshal just assumes that instance
is map[string]interface{}
, so I get a panic when calling vfn.Call(...)
: 事先不知道结构类型,json.Unmarshal只假设instance
是map[string]interface{}
,所以在调用vfn.Call(...)
时我会感到恐慌:
panic: reflect: Call using map[string]interface {} as type main.myStruct
Is it possible to convert the instance
interface into the correct type? 是否可以将instance
接口转换为正确的类型? In other words, can I do type type assertion by passing a string (or using some reflection method) instead of having the type available to the program as a symbol? 换句话说,我可以通过传递字符串(或使用一些反射方法)而不是将程序可用的类型作为符号来键入类型断言吗?
Yes, this is possible. 是的,这是可能的。 Here is your code updated: 这是您的代码更新:
func DoThing(fn interface{}) {
// Get first arg of the function
firstArg := reflect.TypeOf(fn).In(0)
// Get the PtrTo to the first function parameter
structPtr := reflect.New(firstArg)
// Convert to Interface
// Note that I can't assert this to .(myStruct) type
instance := structPtr.Interface()
// Unmarshal the JSON
json.Unmarshal(jsonData, instance)
// Call the function
vfn := reflect.ValueOf(fn)
vfn.Call([]reflect.Value{structPtr.Elem()})
}
Changes made: 做出的改变:
structPtr
(a pointer) to json.Unmarshal
; 将structPtr
(一个指针)传递给json.Unmarshal
; pass a value and you will not see the changes 传递一个值,您将看不到更改 instance
when passing to json.Unmarshal
; 传递给json.Unmarshal
时删除获取instance
的地址; there is usually never a good reason to have a pointer to an interface 通常没有一个很好的理由有一个指向接口的指针 structPtr
instead of instance
when calling fn
在调用fn
时使用structPtr
而不是instance
https://play.golang.org/p/POmOyQBJYC https://play.golang.org/p/POmOyQBJYC
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.