英文:
How read interface value having address of struct
问题
我有一个数据类型为interface{}
的变量,并将结构体的地址传递给它。现在我无法从接口中读取字段。
以下是代码:
type UserData struct {
UserID string `json:"user_id"`
UserName string `json:"user_name"`
}
type Result struct {
Status string `json:"status"`
Data interface{} `json:"data"`
}
var res Result
res.Data = &UserData{}
json.Unmarshal([]byte(`{"status": "success", "data": {"user_id":15,"user_name":"abc"}}`), &res)
fmt.Println(res.Data) // 正常工作
fmt.Println(res.Data.UserName) // 出错:类型interface{}没有字段或方法UserName
如果我使用res.Data.UserName
会出错。
如何从接口中读取结构体字段?
英文:
I have variable with data type interface{}
and passing address of struct to it. now I unable read fields from interface
code as below:
type UserData struct {
UserID string `json:"user_id"`
UserName string `json:"user_name"`
}
type Result struct {
Status string `json:"status"`
Data interface{} `json:"data"`
}
var res Result
res.Data = &UserData
json.Unmarshal([]byte(`{"status": "success", "data": {"user_id":15,"user_name":"abc"}}`), &res)
fmt.Println(res.Data) //working fine
fmt.Println(res.Data.UserName) //getting error: type interface{} has no field or method UserName
if I use res.Data.UserName
getting error
How to read struct fields from interface?
答案1
得分: 2
这与https://stackoverflow.com/questions/76284655/golang-why-does-field-not-existed-in-go-struct-still-present-after-marshaling-sa进行比较很有趣。起初我以为它们是相同的。但事实证明它们并不相同。
对于这个问题,res.Data
保存的是*UserData
类型的值。所以一个简单的类型断言就可以解决。
以下是一个示例代码,合并了@mkopriva的两个示例,并展示了它们之间的区别:
package main
import (
"encoding/json"
"fmt"
"log"
)
type DBBatch struct {
FieldtoKeep string `json:"field_to_keep"`
FieldtoKeep2 string `json:"field_to_keep2"`
}
func main() {
jsonBatch := `{"field_to_keep":"XXXXX","field_to_keep2":"26400527","field_to_delete":"whynotdeleted"}`
var i interface{} = DBBatch{}
fmt.Printf("%T\n", i) // 类型是DBBatch
if err := json.Unmarshal([]byte(jsonBatch), &i); err != nil {
log.Println(err)
}
fmt.Printf("%T\n", i) // 类型不再是DBBatch,而是map[string]interface{}
i = &DBBatch{}
fmt.Printf("%T\n", i) // 类型是*DBBatch
if err := json.Unmarshal([]byte(jsonBatch), &i); err != nil {
log.Println(err)
}
fmt.Printf("%T\n", i) // 类型是*DBBatch
}
输出结果为:
main.DBBatch
map[string]interface {}
*main.DBBatch
*main.DBBatch
英文:
It's interesting to compare this with https://stackoverflow.com/questions/76284655/golang-why-does-field-not-existed-in-go-struct-still-present-after-marshaling-sa. At first I thought they are the same. But it turns out that they are not.
For this question, res.Data
holds a value of type *UserData
. So a simple type assertion will work.
package main
import (
"encoding/json"
"fmt"
)
type UserData struct {
UserID string `json:"user_id"`
UserName string `json:"user_name"`
}
type Result struct {
Status string `json:"status"`
Data interface{} `json:"data"`
}
func main() {
var res Result
res.Data = &UserData{}
json.Unmarshal([]byte(`{"status": "success", "data": {"user_id":15,"user_name":"abc"}}`), &res)
fmt.Println(res.Data)
fmt.Println(res.Data.(*UserData).UserName)
}
The following demo is a merge of @mkopriva's two demos, and it shows the difference:
package main
import (
"encoding/json"
"fmt"
"log"
)
type DBBatch struct {
FieldtoKeep string `json:"field_to_keep"`
FieldtoKeep2 string `json:"field_to_keep2"`
}
func main() {
jsonBatch := `{"field_to_keep":"XXXXX","field_to_keep2":"26400527","field_to_delete":"whynotdeleted"}`
var i interface{} = DBBatch{}
fmt.Printf("%T\n", i) // type is DBBatch
if err := json.Unmarshal([]byte(jsonBatch), &i); err != nil {
log.Println(err)
}
fmt.Printf("%T\n", i) // type is not DBBatch anymore, instead it's map[string]any
i = &DBBatch{}
fmt.Printf("%T\n", i) // type is *DBBatch
if err := json.Unmarshal([]byte(jsonBatch), &i); err != nil {
log.Println(err)
}
fmt.Printf("%T\n", i) // type is *DBBatch
}
The output is:
main.DBBatch
map[string]interface {}
*main.DBBatch
*main.DBBatch
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论