我可以将一段结构传递给函数,转换为[]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 {}?不需要复杂的代码和额外的操作
谢谢你的帮助!
答案 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
答案 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)
}