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
obteniendo Nombre del campo i - esto parece funcionar
var field = reflect.TypeOf(r).Field(i).Name
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())
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
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)
}