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

Go 在函数中传递接口切片,并将其解组到其项中,go,parameters,interface,slice,unmarshalling,Go,Parameters,Interface,Slice,Unmarshalling,我是否可以将转换为[]接口{}的结构片传递到函数中,填充它并在函数结束工作后使用 下面是问题的完整示例 简短描述: type DBResponse struct { Rows int `json:"rows"` Error string `json:"error"` Value json.RawMessage `json:"value"` } type User struct { Id int `json:"i

我是否可以将转换为
[]接口{}
的结构片传递到函数中,填充它并在函数结束工作后使用

下面是问题的完整示例

简短描述:

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)
}
对于单个
接口{}
,这个问题很容易解决,您可以在完整的示例中进行测试。为什么我不能为slice解决它

我想做这件事而不去思考!有没有“真正的方法”可以在没有反射和映射[string]接口{}的情况下将通用json解析器写入选定的数据结构不需要复杂的代码和额外的操作


谢谢你的帮助

因为
p
是接口的一部分,所以在这一行
json.Unmarshal(response.Value,&p[0])
您将指向
接口{}
的指针传递给
用户
,因为
json.Unmarshal
允许接口作为数据解组的目的地,所以它不会查看
接口{}
用于另一种类型,只需将
json
解码为
map

您可以做的是让
接口{}
已经是一个指向具体类型的指针,例如
数据[i]=&users[i]
,然后您只需将
接口{}
传递给
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 &
}

一个选项是使用reflect包访问切片元素

该函数假定
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
。没有必要像问题中那样创建
[]接口{}

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

非常感谢!我应该读更多关于接口转换的内容,你能给我一个建议吗?再次感谢!对于
json.Unmarshal
的转换规则,最好阅读并更好地理解
接口{}
是什么,可以找到一篇很好的文章