Der meiste Code sollte diese Art der dynamischen Suche nicht benötigen. Es ist ineffizient im Vergleich zum direkten Zugriff (der Compiler kennt den Versatz des X-Felds in einer Vertex-Struktur, er kann vX zu einer einzelnen Maschinenanweisung kompilieren, während eine dynamische Suche eine Art Hash-Tabellenimplementierung oder ähnliches erfordert). Es verhindert auch die statische Typisierung: Der Compiler kann nicht überprüfen, ob Sie nicht versuchen, dynamisch auf unbekannte Felder zuzugreifen, und er kann nicht wissen, wie der resultierende Typ aussehen soll.
Aber ... die Sprache bietet ein Reflektionsmodul für die seltenen Fälle, in denen Sie dies benötigen.
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())
}
Hier gibt es keine Fehlerprüfung, sodass Sie in Panik geraten, wenn Sie nach einem Feld fragen, das nicht vorhanden ist, oder wenn das Feld nicht vom Typ int ist. Weitere Informationen finden Sie in der Dokumentation .
Ìndirect
. Vielen Dank für das Arbeitsbeispiel und die Erklärung. Wirklich zu schätzen :-)Sie haben jetzt das Projekt Oleiade / Reflections , mit dem Sie Felder für Strukturwerte oder Zeiger abrufen / festlegen können.
Dies macht die Verwendung des
reflect
Pakets weniger schwierig.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
quelle
Sie können die Struktur marshallen und zurück zu marshallen
map[string]interface{}
. Es werden jedoch alle Zahlenwertefloat64
in konvertiert , sodass Sie sieint
manuell konvertieren müssen.type Vertex struct { X int Y int } func main() { v := Vertex{1, 2} fmt.Println(getProperty(&v, "X")) } func getProperty(v *Vertex, property string) float64 { m, _ := json.Marshal(v) var x map[string]interface{} _ = json.Unmarshal(m, &x) return x[property].(float64) }
quelle