[英]How to make parameter of function is a “generic” struct
例如,我要编写这样的方法:
func parseData(rawData []json.RawMessage) []interface{} {
var migrations []interface{}
for _, migration := range rawData {
// this is an custom struct
command := UserCommand{}
json.Unmarshal(migration, &command)
migrations = append(migrations, command)
}
return migrations
}
该代码的问题是:如果我不想解析UserCommand
但要解析任何其他产品(例如ProductCommand
,则我必须编写相同的代码,只是在以下行不同: command := UserCommand{}
。 所以我的问题是:如何通用此代码。
我已经尝试过此解决方案,但是它不起作用:
func parseData(rawData []json.RawMessage, class interface{}) []interface{} {
var migrations []interface{}
for _, migration := range rawData {
command := class
json.Unmarshal(migration, &command)
migrations = append(migrations, command)
}
return migrations
}
// then I call this method
parseData(data, UserCommand{})
但这是行不通的。 它返回map[string]interface{}
数组。如何解决此问题。
编辑:
这是我定义的一些结构
type UserCommand struct {
User string
Info string
}
type ProductCommand struct {
Name string
Quanlity int
}
// I want to be able to call this method parseData(data, UserCommand{})
通过使用Go的reflect
包,可以支持这种“通用”签名样式。
package main
import (
"encoding/json"
"fmt"
"reflect"
)
type UserCommand struct {
User string
Info string
}
type ProductCommand struct {
Name string
Quantity int
}
func parseData(rawData []json.RawMessage, class interface{}) []interface{} {
var parsed []interface{}
for _, elem := range rawData {
// Create a pointer to a new zero value of the same type as `class`.
command := reflect.New(reflect.TypeOf(class))
// Pass a pointer to the new value to `json.Unmarshal`.
json.Unmarshal(elem, command.Interface())
// Insert the pointed-to new value into the output slice.
parsed = append(parsed, command.Elem().Interface())
}
return parsed
}
func main() {
data := []json.RawMessage{
json.RawMessage(`{"User":"u1","Info":"i1"}`),
json.RawMessage(`{"User":"u2","Info":"i2"}`),
}
parsed := parseData(data, UserCommand{})
fmt.Printf("%#v\n", parsed)
data = []json.RawMessage{
json.RawMessage(`{"Name":"n1","Quantity":1}`),
json.RawMessage(`{"Name":"n2","Quantity":2}`),
}
parsed = parseData(data, ProductCommand{})
fmt.Printf("%#v\n", parsed)
}
输出显示,第一个parseData
调用已解析了两个UserCommand
结构,第二个调用已解析了两个ProductCommand
结构。
[]interface {}{main.UserCommand{User:"u1", Info:"i1"}, main.UserCommand{User:"u2", Info:"i2"}}
[]interface {}{main.ProductCommand{Name:"n1", Quantity:1}, main.ProductCommand{Name:"n2", Quantity:2}}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.