亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

golang reflect 無法識別來自地圖成員的標簽

golang reflect 無法識別來自地圖成員的標簽

Go
飲歌長嘯 2022-11-23 15:29:04
我想用反射提取結構的映射成員的標簽,而我發現如果從 MapIndex 檢索成員的值,它的類型將被識別為“*接口{}”因此所有類型信息都丟失,沒有提到反射可以提取細節信息。package mainimport (    "fmt"    "reflect")type Student struct {    Sname string `MyTag:"student-name"`}type Teacher struct {    Name     string             `MyTag:"teacher-name"`    Students map[string]Student `MyTag:"teacher-students"`}var sam = Teacher{    Name: "Sam",    Students: map[string]Student{        "Sen": {            Sname: "Sen",        },    },}func traversalTag(obj interface{}) {    theType := reflect.TypeOf(obj)    fmt.Printf("Traversal tag with obj: type %v, value %v\n", theType.String(), obj)    elem := reflect.TypeOf(obj).Elem()    for i := 0; i < elem.NumField(); i++ {        fmt.Printf("Tag name %s, value %s\n", elem.Field(i).Name, elem.Field(i).Tag)    }}func tryMapWithType(students map[string]Student) {    for key, theValue := range students {        fmt.Printf("Key: %v, Value: %v, value pointer %p\n", key, theValue, &theValue)        traversalTag(&theValue)    }}func tryMapWithReflect(obj interface{}) {    reflectMap := reflect.ValueOf(obj)    for _, key := range reflectMap.MapKeys() {        theValue := reflectMap.MapIndex(key).Interface()        fmt.Printf("Key: %v, Value: %v, value pointer %p\n", key, theValue, &theValue)        traversalTag(&theValue) // Will have error    }}func main() {    tryMapWithType(sam.Students)    tryMapWithReflect(sam.Students)}運行后出現以下錯誤:Starting: C:\Users\Mento\go\bin\dlv.exe dap --check-go-version=false --listen=127.0.0.1:50308 from d:\Coding\Golang\demoDAP server listening at: 127.0.0.1:50308Key: Sen, Value: {Sen}, value pointer 0xc000044230Traversal tag with obj: type *main.Student, value &{Sen}Tag name Sname, value MyTag:"student-name"Key: Sen, Value: {Sen}, value pointer 0xc0000442c0Traversal tag with obj: type *interface {}, value 0xc0000442c0panic: reflect: NumField of non-struct type interface {}誰能提示如何使用原始類型信息獲取地圖成員的指針?
查看完整描述

1 回答

?
HUX布斯

TA貢獻1876條經驗 獲得超6個贊

如您所知,使用&theValue解析為類型*interface{}。該類型*interface{}不同于*Student您傳遞給traversalTagfrom的類型tryMapWithType。


如果要傳遞*Student給traversalTagfrom tryMapWithReflect,則需要使用反射創建該指針值。簡單的原生 Go 地址運算符&是不夠的。


當您擁有reflect.Value可尋址的 a 時,您需要做的就是調用該.Addr()方法以獲取指向可尋址值的指針,但是映射元素不可尋址,因此reflectMap.MapIndex(key)不可尋址。所以,不幸的是,你無法reflectMap.MapIndex(key).Addr().Interface()獲得*Student.


因此,您唯一的選擇是使用反射來創建該*Student類型的新值,將指向的值設置為映射中的值,然后返回該類型的值.Interface()。


func tryMapWithReflect(obj interface{}) {

    reflectMap := reflect.ValueOf(obj)

    for _, key := range reflectMap.MapKeys() {

        theValue := reflectMap.MapIndex(key).Interface()


        // allocate a new value of type *Student

        newValue := reflect.New(reflectMap.MapIndex(key).Type())


        // use Elem do dereference *Stunded

        // and then use Set to set the Student to the content of theValue

        newValue.Elem().Set(reflect.ValueOf(theValue))


        fmt.Printf("Key: %v, Value: %v, value pointer %p\n", key, newValue.Elem().Interface(), newValue.Interface())


        // return the newValue *Student

        traversalTag(newValue.Interface())

    }

}

https://go.dev/play/p/pNL2wjsOW5y


.Elem()或者,只需從 the 中刪除 thetraversalTag然后就不必將指針傳遞給它。


func traversalTag(obj interface{}) {

    theType := reflect.TypeOf(obj)

    fmt.Printf("Traversal tag with obj: type %v, value %v\n", theType.String(), obj)


    elem := reflect.TypeOf(obj)

    for i := 0; i < elem.NumField(); i++ {

        fmt.Printf("Tag name %s, value %s\n", elem.Field(i).Name, elem.Field(i).Tag)

    }

}

https://go.dev/play/p/EwJ5e0uc2pd


查看完整回答
反對 回復 2022-11-23
  • 1 回答
  • 0 關注
  • 178 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號