J'essaie de créer une fonction qui pourrait accepter la suite
*struct
[]*struct
map[string]*struct
Ici, struct peut être n'importe quelle structure et pas seulement une structure spécifique. Conversion de l'interface en *struct
ou []*struct
fonctionne bien. Mais donnant une erreur pour la carte.
Après réflexion, il montre qu'il s'agit de la carte [] mais donne une erreur lors d'une tentative d'itération sur la plage.
Voici le code
package main
import (
"fmt"
"reflect"
)
type Book struct {
ID int
Title string
Year int
}
func process(in interface{}, isSlice bool, isMap bool) {
v := reflect.ValueOf(in)
if isSlice {
for i := 0; i < v.Len(); i++ {
strct := v.Index(i).Interface()
//... proccess struct
}
return
}
if isMap {
fmt.Printf("Type: %v\n", v) // map[]
for _, s := range v { // Error: cannot range over v (type reflect.Value)
fmt.Printf("Value: %v\n", s.Interface())
}
}
}
func main() {
b := Book{}
b.Title = "Learn Go Language"
b.Year = 2014
m := make(map[string]*Book)
m["1"] = &b
process(m, false, true)
}
Existe-t-il un moyen de convertir interface{}
pour mapper et itérer ou obtenir ses éléments.
Si la valeur de la carte peut être de n'importe quel type, utilisez la réflexion pour parcourir la carte:
if v.Kind() == reflect.Map {
for _, key := range v.MapKeys() {
strct := v.MapIndex(key)
fmt.Println(key.Interface(), strct.Interface())
}
}
S'il y a un petit ensemble connu de types de struct, alors un type switch peut être utilisé:
func process(in interface{}) {
switch v := in.(type) {
case map[string]*Book:
for s, b := range v {
// b has type *Book
fmt.Printf("%s: book=%v\n" s, b)
}
case map[string]*Author:
for s, a := range v {
// a has type *Author
fmt.Printf("%s: author=%v\n" s, a)
}
case []*Book:
for i, b := range v {
fmt.Printf("%d: book=%v\n" i, b)
}
case []*Author:
for i, a := range v {
fmt.Printf("%d: author=%v\n" i, a)
}
case *Book:
fmt.Ptintf("book=%v\n", v)
case *Author:
fmt.Printf("author=%v\n", v)
default:
// handle unknown type
}
}
Vous n'avez pas besoin de réfléchir ici. Essayer:
v, ok := in.(map[string]*Book)
if !ok {
// Can't assert, handle error.
}
for _, s := range v {
fmt.Printf("Value: %v\n", s)
}
Il en va de même pour le reste de votre fonction. Il semble que vous utilisiez la réflexion alors que vous seriez mieux servi par un type switch .
Alternativement, si vous insistez pour utiliser la réflexion ici (ce qui n'a pas beaucoup de sens), vous pouvez également utiliser Value.MapKeys
avec le résultat de votre ValueOf (voir la réponse https://stackoverflow.com/a/38186057/714501 )