reflect golang example go reflection go-reflect

example - reflect golang



Usando reflect, ¿cómo establece el valor de un campo struct? (2)

teniendo problemas para trabajar con campos struct usando el paquete reflect. en particular, no han descubierto cómo establecer el valor del campo.

type t struct { fi int; fs string } var r t = t{ 123, "jblow" } var i64 int64 = 456

  1. obteniendo Nombre del campo i - esto parece funcionar

    var field = reflect.TypeOf(r).Field(i).Name

  2. obtener valor del campo i como a) interfaz {}, b) int - esto parece funcionar

    var iface interface{} = reflect.ValueOf(r).Field(i).Interface()

    var i int = int(reflect.ValueOf(r).Field(i).Int())

  3. valor de ajuste del campo i - pruebe uno - pánico

    reflect.ValueOf(r).Field(i).SetInt( i64 )

    pánico : reflect.Value · SetInt usando el valor obtenido usando el campo no exportado

    asumiendo que no le gustaban los nombres de campo "id" y "name", por lo que renombraron a "Id" y "Name"

    a) ¿Es correcta esta suposición?

    b) si es correcto, no es necesario, ya que en el mismo archivo / paquete

  4. valor de ajuste del campo i - pruebe dos (con los nombres de campo en mayúscula) - pánico

    reflect.ValueOf(r).Field(i).SetInt( 465 )

    reflect.ValueOf(r).Field(i).SetInt( i64 )

    pánico : reflect.Value · SetInt usando un valor no direccionable

Las instrucciones a continuación por @peterSO son exhaustivas y de alta calidad

Las cuatro. esto funciona:

reflect.ValueOf(&r).Elem().Field(i).SetInt( i64 )

él documenta también que los nombres de campo deben ser exportables (comience con la letra mayúscula)


Esto parece funcionar:

package main import ( "fmt" "reflect" ) type Foo struct { Number int Text string } func main() { foo := Foo{123, "Hello"} fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) reflect.ValueOf(&foo).Elem().Field(0).SetInt(321) fmt.Println(int(reflect.ValueOf(foo).Field(0).Int())) }

Huellas dactilares:

123 321


Go está disponible como código fuente abierto . Una buena forma de aprender sobre la reflexión es ver cómo la utilizan los desarrolladores centrales de Go. Por ejemplo, los fmt Go fmt y json . La documentación del paquete tiene enlaces a los archivos de código fuente bajo el encabezado Archivos de paquete.

El paquete Go json reúne y elimina las estructuras JSON de y para Ir.

Aquí hay un ejemplo paso a paso que establece el valor de un campo de struct evitando al mismo tiempo los errores.

El paquete Go CanAddr tiene una función CanAddr .

func (v Value) CanAddr() bool

CanAddr devuelve verdadero si la dirección del valor se puede obtener con Addr. Dichos valores se llaman direccionables. Un valor es direccionable si es un elemento de un sector, un elemento de un conjunto direccionable, un campo de una estructura direccionable o el resultado de desreferenciar un apuntador. Si CanAddr devuelve falso, llamar a Addr entrará en pánico.

El paquete Go CanSet tiene una función CanSet , que, si es true , implica que CanAddr también es true .

func (v Value) CanSet() bool

CanSet devuelve verdadero si se puede cambiar el valor de v. Un valor solo se puede cambiar si es direccionable y no se obtuvo mediante el uso de campos de estructura no exportados. Si CanSet devuelve falso, llamar a Set o a cualquier setter específico de tipo (p. Ej., SetBool, SetInt64) entrará en pánico.

Necesitamos asegurarnos de que podamos Set el campo de struct . Por ejemplo,

package main import ( "fmt" "reflect" ) func main() { type t struct { N int } var n = t{42} // N at start fmt.Println(n.N) // pointer to struct - addressable ps := reflect.ValueOf(&n) // struct s := ps.Elem() if s.Kind() == reflect.Struct { // exported field f := s.FieldByName("N") if f.IsValid() { // A Value can be changed only if it is // addressable and was not obtained by // the use of unexported struct fields. if f.CanSet() { // change value of N if f.Kind() == reflect.Int { x := int64(7) if !f.OverflowInt(x) { f.SetInt(x) } } } } } // N at end fmt.Println(n.N) } Output: 42 7

Si podemos estar seguros de que todas las comprobaciones de error son innecesarias, el ejemplo se simplifica a,

package main import ( "fmt" "reflect" ) func main() { type t struct { N int } var n = t{42} fmt.Println(n.N) reflect.ValueOf(&n).Elem().FieldByName("N").SetInt(7) fmt.Println(n.N) }