go - definicion - estructura de la propiedad de la tierra
Acceso a la propiedad de estructura por nombre (2)
Aquí hay un programa simple que no funciona:
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]
}
Error: prog.go:18: invalid operation: v[property] (index of type *Vertex)
Lo que quiero es acceder a la propiedad Vertex X usando su nombre. Si lo hago, vX
funciona, pero v["X"]
no funciona.
¿Puede alguien decirme cómo hacer que esto funcione?
Ahora tiene el proyecto oleiade/reflections que le permite obtener / establecer campos en valor de estructura o punteros.
Hace que usar el reflect reflect sea menos complicado.
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
La mayoría del código no debería necesitar este tipo de búsqueda dinámica. Es ineficiente en comparación con el acceso directo (el compilador conoce el desplazamiento del campo X en una estructura Vertex, puede compilar vX en una sola instrucción de máquina, mientras que una búsqueda dinámica necesitará algún tipo de implementación de tabla hash o similar). También inhibe el tipado estático: el compilador no tiene manera de verificar que no intente acceder a campos desconocidos dinámicamente, y no puede saber cuál debería ser el tipo resultante.
Pero ... el lenguaje proporciona un módulo de reflect para los raros momentos que necesita esto.
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())
}
No hay ningún error al verificar aquí, por lo que tendrá pánico si solicita un campo que no existe, o si el campo no es de tipo int. Verifique reflect para más detalles.