所以我找到了一些代码来帮助我开始使用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中获取底层值?
4条答案
按热度按时间gcuhipw91#
fmt
包就是一个很好的解析值的例子。使用上面提到的代码来匹配您的问题看起来像这样:
基本上你需要检查所有可用的类型。
mbyulnm02#
看起来你走在正确的轨道上。我看到你的代码的问题是它对值进行了假设,这意味着你什么时候调用
Elem()
以及多少次(解析指针)。为了知道这个,你需要查看reflect.Kind
。这个值是reflect.Ptr
吗?然后使用Elem()
。一旦你有了
val.Interface()
/val.String()
/val.Int()
的值,你就可以根据需要转换你的值。你使用的是什么取决于reflect.Kind
。要将int
转换为string
,你需要使用strconv
包。encoding/json
和encoding/xml
包已经完成了这类工作。源代码提供了一些很好的例子。例如,看看encoding/xml/read.go中的copyValue
和encoding/xml/marshal.go中的marshalSimple
。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
的内容,就好像 that 是Printf
的参数一样。这可以说是一个突破性的变化,但我认为这是一个真正的改进,并没有比我们对这个包的格式化输出所做的许多其他调整更大的突破。
o2gm4chl4#
另一种简单的解决方案可以是,
“fmt.Sprintf()“将返回可以存储在变量中的值。