For example, I want to write a method like this:
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
}
The problem of this code is: If I don't want to parse UserCommand
but any other such as ProductCommand
, I must write the same code, only different at line: command := UserCommand{}
. So my question is: how can I generic this code.
I have tried this solution but it doesn't work:
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{})
But it doesn't work. It return array of map[string]interface{}
How can I fix this.
Edit:
Here is some my defined struct
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{})
It is possible to support this style of "generic" signature by using Go's reflect
package.
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)
}
The output shows that the first parseData
call has parsed two UserCommand
structs and the second call has parsed two ProductCommand
structs.
[]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}}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.