91

これは、動作していない単純な go プログラムです。

package main
import "fmt"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    fmt.Println(getProperty(&v, "X"))
}

func getProperty(v *Vertex, property string) (string) {
    return v[property]
}

エラー:

prog.go:18: 無効な操作: v[property] (タイプ *Vertex のインデックス)

私が望むのは、その名前を使用して Vertex X プロパティにアクセスすることです。私がやればv.Xうまくいきますが、うまくいきv["X"]ません。

誰かがこれを機能させる方法を教えてもらえますか?

4

4 に答える 4

130

ほとんどのコードでは、この種の動的ルックアップは必要ありません。直接アクセスと比較すると非効率的です (コンパイラは Vertex 構造体の X フィールドのオフセットを認識しており、vX を単一のマシン命令にコンパイルできますが、動的ルックアップには何らかのハッシュ テーブルの実装などが必要になります)。また、静的型付けも禁止します。コンパイラには、不明なフィールドに動的にアクセスしようとしていないことを確認する方法がなく、結果の型がどうあるべきかを知ることができません。

しかし...言語は、これが必要なまれな場合に備えてリフレクトモジュールを提供します。

package main

import "fmt"
import "reflect"

type Vertex struct {
    X int
    Y int
}

func main() {
    v := Vertex{1, 2}
    fmt.Println(getField(&v, "X"))
}

func getField(v *Vertex, field string) int {
    r := reflect.ValueOf(v)
    f := reflect.Indirect(r).FieldByName(field)
    return int(f.Int())
}

ここにはエラー チェックがないため、存在しないフィールドを要求したり、フィールドの型が int でなかったりすると、パニックが発生します。詳細については、reflect のドキュメントを確認してください。

于 2013-09-21T09:27:13.363 に答える
20

これで、構造体値またはポインターのフィールドを取得/設定できるプロジェクトoleiade/reflectionsが作成されました。パッケージ
の使用が簡単になります。reflect

s := MyStruct {
    FirstField: "first value",
    SecondField: 2,
    ThirdField: "third value",
}

fieldsToExtract := []string{"FirstField", "ThirdField"}

for _, fieldName := range fieldsToExtract {
    value, err := reflections.GetField(s, fieldName)
    DoWhatEverWithThatValue(value)
}


// In order to be able to set the structure's values,
// a pointer to it has to be passed to it.
_ := reflections.SetField(&s, "FirstField", "new value")

// If you try to set a field's value using the wrong type,
// an error will be returned
err := reflection.SetField(&s, "FirstField", 123)  // err != nil
于 2014-09-02T05:26:37.900 に答える