在函数中传递接口切片并解组到其项目中

时间:2017-03-26 21:45:29

标签: go parameters interface slice unmarshalling

我可以将一段结构传递给函数,转换为[]interface{},填充它并在函数结束后使用吗?

以下是问题https://play.golang.org/p/iPijsawEEg

的完整示例

简短描述:

type DBResponse struct {
    Rows  int             `json:"rows"`
    Error string          `json:"error"`
    Value json.RawMessage `json:"value"`
}
type User struct {
    Id   int    `json:"id"`
    Name string `json:"name"`
}

func loadDBRows(p []interface{}) {
    var response DBResponse
    someDataFromDB := []byte("{\"rows\":1, \"error\": \"\", \"value\": {\"name\":\"John\", \"id\":2}}")
    json.Unmarshal(someDataFromDB, &response)
    json.Unmarshal(response.Value, &p[0])
    fmt.Println(p)//p[0] filled with map, not object
}

func main() {
    users := make([]User, 5)
    data := make([]interface{}, 5)
    for i := range users {
        data[i] = users[i]
    }
    loadDBRows(data)
}

单个interface{}可以轻松解决此问题,您可以在完整示例中进行测试。为什么我不能解决它?

我想在没有反映的情况下这样做!有没有“真正的方法”将通用json解析器写入选定的数据struct 而不使用reflect和map [string] interface {}?不需要复杂的代码和额外的操作

谢谢你的帮助!

2 个答案:

答案 0 :(得分:0)

由于p是一个接口片段,因此在这一行json.Unmarshal(response.Value, &p[0])上您将指针传递给interface{}而不是User,并且json.Unmarshal以及interface{} 1}}允许接口作为解组数据的目标,它不会在json下查找另一种类型,只需将map解码为interface{}。< / p>

你可以做的是让data[i] = &users[i]已经是指向具体类型的指针,例如interface{}然后您只需将& json.Unmarshal传递给func loadDBRows(p []interface{}) { var response DBResponse someDataFromDB := []byte("{\"rows\":1, \"error\": \"\", \"value\": {\"name\":\"John\", \"id\":2}}") json.Unmarshal(someDataFromDB, &response) json.Unmarshal(response.Value, p[0]) // notice the missing & fmt.Println(p) } users := make([]User, 5) data := make([]interface{}, 5) for i := range users { data[i] = &users[i] // notice the added & }

lambda

https://play.golang.org/p/GEbIq9febY

答案 1 :(得分:0)

一种选择是使用反射包来访问切片元素。

该函数假定p是切片:

func loadDBRows(p interface{}) {
  var response DBResponse
  someDataFromDB := []byte("{\"rows\":1, \"error\": \"\", \"value\": {\"name\":\"John\", \"id\":2}}")
  json.Unmarshal(someDataFromDB, &response)
  v := reflect.ValueOf(p). // get reflect.Value for argument
               Index(0).   // get first element assuming that p is a slice
               Addr().     // take address of the element
               Interface() // get the pointer to element as an interface{}
  json.Unmarshal(response.Value, v)
}

像这样使用loadDBRows。没有必要在问题中创建[]interface{}

func main() {
  users := make([]User, 5)
  loadDBRows(users)
  fmt.Println(users)
}

playground example