Acceso a la estructura de la propiedad por su nombre

Aquí es un simple ir de programa 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]
}

De Error:

prog.ir:18: operación no válida: v[propiedad] (índice de tipo *Vértice)

Lo que quiero es acceder al Vértice X de la propiedad en su nombre. Si hago v.X funciona, pero v["X"] no.

Alguien me puede decir cómo hacer este trabajo ?

2 Kommentare

  1. 95

    Código de la mayoría no necesitan este tipo de búsqueda dinámica. Es ineficiente en comparación con acceso directo (el compilador sabe que el desplazamiento de la X de campo en un Vértice de la estructura, se puede compilar v. X X X X para una sola instrucción de la máquina, mientras que una búsqueda dinámica necesitará algún tipo de tabla hash aplicación o similar). También inhibe la estáticos: el compilador no tiene forma de comprobar que no estás tratando de acceder desconocido campos dinámicamente, y no puede saber lo que el tipo resultante debe ser.

    Pero… el lenguaje proporciona un reflexionar módulo para las pocas veces que lo necesites.

    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())
    }

    Hay ninguna comprobación de errores aquí, así que van a tener un ataque de pánico si usted solicita un campo que no existe, o el campo no es de tipo int. Compruebe la documentación para reflejar para obtener más detalles.

    • +1, y véase también las Leyes de La Reflexión que se da una introducción a la idea.
    • Esto se refleja módulo es un poco complicado. Traté de utilizarlo sin éxito. Parece que se me fue olvidando a llamar Ìndirect. Gracias por el ejemplo de trabajo y toda la explicación. Realmente aprecio 🙂
    • Gracias por la explicación sobre el código. Para mí, es incluso más útil que el propio código!
  2. 10

    Ahora tiene el proyecto oleiade/reflexiones que le permite obtener/establecer campos en la estructura de valor o punteros.

    Esto hace que el uso de la reflejar paquete 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

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea