如何从golang中的reflect.Value获取基础值?

luc*_*iet 30 reflection go

所以我找到了一些代码来帮助我开始使用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)
}
Run Code Online (Sandbox Code Playgroud)

运行代码的输出:

FirstName : Drew
LastName : Olson
Age : <int Value>
Run Code Online (Sandbox Code Playgroud)

根据我的理解,FirstName和LastName的输出是实际的reflect.Value对象,但对于字符串,值上的String()方法只输出底层的String.我想要获取int并将其更改为字符串,但是从relfect包文档中我不会立即看到它是如何完成的.

Soo ....如何从golang中的reflect.Value中获取基础值?

nem*_*emo 15

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...
}
Run Code Online (Sandbox Code Playgroud)

基本上你需要检查所有可用的种类.


Luk*_*uke 5

看起来你走在正确的轨道上。我在您的代码中看到的问题是它对值进行了假设,这意味着您何时调用Elem()以及调用了多少次(以解析指针)。为了知道这一点,您需要查看reflect.Kind. 值是 areflect.Ptr吗?然后使用Elem().

一旦你从价值val.Interface()/ val.String()/val.Int() 你可以根据需要转换你的价值观。你使用什么将取决于reflect.Kind. 要转换int为/从string您需要使用strconv包。

encoding/jsonencoding/xml包做这方面的工作了。源代码提供了一些很好的示例。例如,看看copyValue编码/ XML / read.gomarshalSimple编码/ XML / marshal.go


Von*_*onC 5

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

fmt:特殊对待reflect.Value- 作为其所拥有的价值

这将允许您打印Reflect.Value()参数的实际值:

当areflect.Value被传递给Printf(etc)时,fmt调用该String方法,该方法不公开其内容。
要获取内容,可以调用,但如果未导出或以其他方式禁止,Value.Interface()则这是非法的。Value

这个 CL 通过对包进行一个微小的更改来改善这种情况fmt:当我们将 a 视为reflect.Value参数时,我们对待它的方式与我们reflect.Value在包内创建的 a 完全一样。
这意味着我们总是打印 的内容,Value就好像是 的参数一样Printf

这可以说是一个突破性的改变,但我认为这是一个真正的改进,并且与我们对该包的格式化输出所做的许多其他调整相比,没有更大的突破。