考虑一下:
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)
})
}
我是Go的新手,所以我担心这可能不是惯用代码。我想实现somelibrary.DoThing
所以如果可能,它通过反射正确地从函数参数中推断出结构类型。这就是我所拥有的:
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)})
}
事先不知道结构类型,json.Unmarshal只假设instance
是map[string]interface{}
,所以在调用vfn.Call(...)
时我会感到恐慌:
panic: reflect: Call using map[string]interface {} as type main.myStruct
是否可以将instance
接口转换为正确的类型?换句话说,我可以通过传递字符串(或使用一些反射方法)来键入类型断言,而不是将程序可用的类型作为符号吗?
答案 0 :(得分:3)
是的,这是可能的。这是您的代码更新:
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()})
}
所做的更改:
structPtr
(指针)传递给json.Unmarshal
;传递值,您将看不到更改instance
时删除json.Unmarshal
的地址; there is usually never a good reason to have a pointer to an interface structPtr
instance
代替fn
醇>