reflection - una - mercado de derivados ejemplos
¿Cómo obtener valor subyacente de un reflejo.Valor en golang? (3)
Así que encontré un código que me ayudó a comenzar con la reflexión en Go (golang), pero tengo problemas para obtener el valor subyacente, por lo que básicamente puedo crear una map[string]string
de una estructura y sus campos.
Finalmente, me gustaría convertir el resultado en una map[string]interface{}
, pero este único problema me está bloqueando.
El código que tengo en este momento:
package main
import (
"fmt"
"reflect"
)
type Foo struct {
FirstName string `tag_name:"tag 1"`
LastName string `tag_name:"tag 2"`
Age int `tag_name:"tag 3"`
}
func inspect(f interface{}) map[string]string {
m := make(map[string]string)
val := reflect.ValueOf(f).Elem()
for i := 0; i < val.NumField(); i++ {
valueField := val.Field(i)
typeField := val.Type().Field(i)
f := valueField.Interface()
val := reflect.ValueOf(f)
m[typeField.Name] = val.String()
}
return m
}
func dump(m map[string]string) {
for k, v := range m {
fmt.Printf("%s : %s/n", k, v)
}
}
func main() {
f := &Foo{
FirstName: "Drew",
LastName: "Olson",
Age: 30,
}
a := inspect(f)
dump(a)
}
La salida de ejecutar el código:
FirstName : Drew
LastName : Olson
Age : <int Value>
Por lo que entiendo, la salida para FirstName y LastName son objetos reflect.Value reales, pero para las cadenas, el método String () en el valor solo genera la cadena subyacente. Me gustaría obtener el int y cambiarlo en una cadena, pero de la documentación del paquete de relfect no veo de inmediato cómo se hace.
Soo .... ¿Cómo obtengo el valor subyacente de un reflejo.Valor en golang?
Esto debería ser más fácil de hacer con Go 1.5 (agosto de 2015) Ver la revisión 8731 y confirmar 049b89d por Rob Pike ( robpike
) :
fmt
: treatreflect.Value
especialmente - como el valor que tiene
Esto le permitiría imprimir el valor real de un argumento Reflect.Value()
:
Cuando se pasa un valor
reflect.Value
aPrintf
(etc.),fmt
llama métodoString
, que no revela su contenido.
Para obtener el contenido, se podría llamar aValue.Interface()
, pero eso es ilegal si elValue
no se exporta o está prohibido.Este CL mejora la situación con un cambio trivial en el paquete
fmt
: cuando vemos unreflect.Value
como un argumento, lo tratamos exactamente como tratamos unreflect.Value
lo hacemos dentro del paquete.
Esto significa que siempre imprimimos el contenido delValue
como si ese fuera el argumento dePrintf
.Podría decirse que este es un cambio importante, pero creo que es una mejora genuina y no una ruptura mayor que muchas otras modificaciones que hemos realizado en la salida con formato de este paquete.
Parece que estás en el camino correcto. El problema que veo con su código es que hace suposiciones sobre los valores, es decir, cuándo llama a Elem()
y cuántas veces (para resolver los punteros). Para saber esto necesitas mirar el reflect.Kind
. reflect.Kind
. ¿Es el valor un reflect.Ptr
? Luego usa Elem()
.
Una vez que tenga el valor de val.Interface()
/ val.String()
/ val.Int()
puede convertir sus valores según sea necesario. Lo que uses dependerá de reflect.Kind
. Para convertir un int
a / desde una string
, debe usar el paquete strconv
.
Los paquetes encoding/json
y encoding/xml
realizan este tipo de trabajo. El código fuente proporciona algunos grandes ejemplos. Por ejemplo, eche un vistazo a copyValue
en encoding/xml/read.go y marshalSimple
en encoding/xml/marshal.go .
Un buen ejemplo de cómo analizar valores es el paquete fmt
. Ver este codigo
El uso del código mencionado para que coincida con su problema se vería así:
switch val.Kind() {
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
m[typeField.Name] = strconv.FormatInt(val.Int(), 10)
case reflect.String:
m[typeField.Name] = val.String()
// etc...
}
Básicamente necesitas verificar todas las clases disponibles .