9

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を使ってみたかった:)

4

2 に答える 2

7

パッケージfunc (v Value) FieldByName(name string) Valueから使用できます:reflect

FieldByName は、指定された名前の構造体フィールドを返します。フィールドが見つからない場合は、ゼロの値を返します。v の Kind が構造体でない場合はパニックになります。

この作業サンプル コードのように:

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
于 2016-08-14T03:42:13.353 に答える
1

私はprotobufの内部に精通していないか、それを行う手段が提供されているかどうかを知りません。

ただし、(1)説明した方法で値を読み取りたい場合-フィールドを動的にチェーンすることにより、(2)複数回読み取りたい場合。私はそれをjsonにシリアル化し、このパッケージを使用します。それは非常に高速で、(ほぼ) 同じセマンティックを提供します。

// assuming your object got marshaled to this for example
json := `{"name":{"first":"Janet","last":"Prichard"},"age":47}`
value := gjson.Get(json, "name.last")
println(value.String())
于 2016-08-14T11:28:20.843 に答える