mik*_*ike 7 reflection variables dynamic go go-reflect
在Go中,我想做这样的事情.我有一个包含许多结构的大对象(使用Google的protobuf).这是一个人为的例子:
person.name = "testing"
person.address.street = "123 test st"
person.address.city = "tester"
person.address.zip = 90210
person.billing.address.same = true
我希望能够动态地引用一些东西.例如:
key := "person.address.zip"
fmt.Println("the value of key: " + key) // would like to get 90210
key := "person.address.city"
fmt.Println("the value of key: " + key) // would like to get "tester"
Go有可能吗?如果是的话,我怎么能这样做?基本上,我正在创建一个只包含对象子集的报告,我希望能够创建一个映射文件,用户可以将键/值映射到一起,我的程序将输出值.我有这个在python中工作,但想尝试使用Go :)
小智 6
您可以使用func (v Value) FieldByName(name string) Value从reflect包:
FieldByName返回具有给定名称的struct字段.如果未找到任何字段,则返回零值.如果v的Kind不是struct,那就恐慌了.
像这个工作示例代码:
package main
import "fmt"
import "reflect"
func main() {
    person := Person{}
    person.name = "testing"
    person.address.street = "123 test st"
    person.address.city = "tester"
    person.address.zip = 90210
    person.billing.address.same = true
    v := reflect.ValueOf(person)
    f := v.FieldByName("address")
    key := f.FieldByName("zip")
    fmt.Println(key)                   // 90210
    fmt.Println(f.FieldByName("city")) // tester    
}
type Person struct {
    name    string
    address Address
    billing Billing
}
type Billing struct {
    address Address
}
type Address struct {
    street, city string
    zip          int
    same         bool
}
输出:
90210
tester
对于您的特殊情况,您可以使用fmt.Println(field(person, "person.address.zip")),如此工作示例代码(仅用于演示):  
package main
import "fmt"
import "reflect"
import "strings"
func field(t interface{}, key string) reflect.Value {
    strs := strings.Split(key, ".")
    v := reflect.ValueOf(t)
    for _, s := range strs[1:] {
        v = v.FieldByName(s)
    }
    return v
}
func main() {
    person := Person{}
    person.name = "testing"
    person.address.street = "123 test st"
    person.address.city = "tester"
    person.address.zip = 90210
    person.billing.address.same = true
    fmt.Println(field(person, "person.address.zip"))  //90210
    fmt.Println(field(person, "person.address.city")) //tester
}
type Person struct {
    name    string
    address Address
    billing Billing
}
type Billing struct {
    address Address
}
type Address struct {
    street, city string
    zip          int
    same         bool
}
输出:
90210
tester