如何从Golang的反映价值中获取潜在价值?

vi4fp9gy  于 2023-04-27  发布在  Go
关注(0)|答案(4)|浏览(145)

所以我找到了一些代码来帮助我开始使用Go(golang)中的反射,但是我在获取底层值时遇到了麻烦,这样我就可以基本上从结构体及其字段创建map[string]string
最后,我想把结果变成map[string]interface{},但是这个问题有点让我困惑。
我现在的代码:

package main

import (
    "fmt"
    "reflect"
)

type Foo struct {
    FirstName string `tag_name:"tag 1"`
    LastName  string `tag_name:"tag 2"`
    Age       int  `tag_name:"tag 3"`
}

func inspect(f interface{}) map[string]string {

    m := make(map[string]string)
    val := reflect.ValueOf(f).Elem()

    for i := 0; i < val.NumField(); i++ {
        valueField := val.Field(i)
        typeField := val.Type().Field(i)

        f := valueField.Interface()
        val := reflect.ValueOf(f)
        m[typeField.Name] = val.String()
    }

    return m
}

func dump(m map[string]string) {

    for k, v := range m {
        fmt.Printf("%s : %s\n", k, v)
    }
}

func main() {
    f := &Foo{
        FirstName: "Drew",
        LastName:  "Olson",
        Age:       30,
    }

    a := inspect(f)

    dump(a)
}

运行代码的输出:

FirstName : Drew
LastName : Olson
Age : <int Value>

据我所知,FirstName和LastName的输出实际上是reflect.Value对象,但对于字符串,value的String()方法只输出底层的String。我想获取int并将其更改为字符串,但从relfect包文档中我没有立即看到如何完成。
如何从golang中的reflect.Value中获取底层值?

gcuhipw9

gcuhipw91#

fmt包就是一个很好的解析值的例子。
使用上面提到的代码来匹配您的问题看起来像这样:

switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
    m[typeField.Name] = strconv.FormatInt(val.Int(), 10)
case reflect.String:
    m[typeField.Name] = val.String()    
// etc...
}

基本上你需要检查所有可用的类型。

mbyulnm0

mbyulnm02#

看起来你走在正确的轨道上。我看到你的代码的问题是它对值进行了假设,这意味着你什么时候调用Elem()以及多少次(解析指针)。为了知道这个,你需要查看reflect.Kind。这个值是reflect.Ptr吗?然后使用Elem()
一旦你有了val.Interface()/val.String()/val.Int()的值,你就可以根据需要转换你的值。你使用的是什么取决于reflect.Kind。要将int转换为string,你需要使用strconv包。
encoding/jsonencoding/xml包已经完成了这类工作。源代码提供了一些很好的例子。例如,看看encoding/xml/read.go中的copyValueencoding/xml/marshal.go中的marshalSimple

pinkon5k

pinkon5k3#

Go 1.5(2015年8月)应该更容易做到这一点,请参阅Rob Pike ( robpike )的评论8731和commit 049b89d

fmt:特别对待reflect.Value-它持有的值

这将允许您打印Reflect.Value()参数的实际值:
reflect.Value传递给Printf(等等)时,fmt调用String方法,该方法没有公开其内容。
要获取内容,可以调用Value.Interface(),但如果Value未导出或被禁止,则这是非法的。
此CL通过对fmt包的微小更改改善了这种情况:当我们看到一个reflect.Value作为一个参数时,我们对待它就像对待我们在包中创建的reflect.Value一样。
这意味着我们总是打印Value的内容,就好像 thatPrintf的参数一样。
这可以说是一个突破性的变化,但我认为这是一个真正的改进,并没有比我们对这个包的格式化输出所做的许多其他调整更大的突破。

o2gm4chl

o2gm4chl4#

另一种简单的解决方案可以是,

flavorName = fmt.Sprintf("%v",strct)

fmt.Sprintf()“将返回可以存储在变量中的值。

相关问题