如何读取具有结构体地址的接口值

huangapple go评论74阅读模式
英文:

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

huangapple
  • 本文由 发表于 2023年5月27日 16:43:01
  • 转载请务必保留本文链接:https://go.coder-hub.com/76346054.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定