J'ai trouvé cette question avec ces excellentes réponses:
Comment trouver un type d'objet à Golang?
J'ai joué avec la réponse et j'ai essayé d'obtenir le nom d'une structure de la même manière:
package main
import (
"fmt"
"reflect"
)
type Ab struct {
}
func getType(myvar interface{}) string {
return reflect.TypeOf(myvar).Name()
}
func main() {
fmt.Println("Hello, playground")
tst := "string"
tst2 := 10
tst3 := 1.2
tst4 := new(Ab)
fmt.Println(getType(tst))
fmt.Println(getType(tst2))
fmt.Println(getType(tst3))
fmt.Println(getType(tst4))
}
Allez aire de jeux: http://play.golang.org/p/tD8mygvETH
Mais la sortie est:
Hello, playground
string
int
float64
Program exited.
La sortie attendue serait:
Hello, playground
string
int
float64
Ab
Program exited.
J'ai essayé de comprendre en lisant la documentation mais je n'ai pas trouvé le problème à ce sujet. Donc, désolé pour la question très générale, mais:
Quelle est la raison, reflect.TypeOf().Name()
ne fonctionne pas avec (cette) structure (s)?
Dans votre exemple, vous passez une valeur de type pointeur (*Ab
), Pas un type struct.
Type.Name()
S'il ne s'agit pas d'un pointeur, Type.Name()
renverra correctement Ab
. En cas de pointeur si vous voulez toujours le nom de la structure, vous pouvez utiliser Type.Elem()
pour obtenir le type de l'élément:
func getType(myvar interface{}) string {
if t := reflect.TypeOf(myvar); t.Kind() == reflect.Ptr {
return "*" + t.Elem().Name()
} else {
return t.Name()
}
}
Le tester:
tst4 := Ab{}
tst5 := new(Ab)
fmt.Println(getType(tst4))
fmt.Println(getType(tst5))
Sortie (essayez votre exemple modifié sur le Go Playground ):
Ab
*Ab
Remarque:
Notez que comme Type.Name()
ne résout pas les pointeurs, cela ne fonctionnerait pas si la valeur transmise est un pointeur à pointeur, par ex. **Ab
, Alors que Type.String()
résout automatiquement les pointeurs, cela fonctionnerait aussi dans ce cas.
Nous pouvons facilement faire fonctionner notre fonction getType()
avec **Ab
(Ou avec n'importe quelle profondeur de pointeurs):
func getType(myvar interface{}) (res string) {
t := reflect.TypeOf(myvar)
for t.Kind() == reflect.Ptr {
t = t.Elem()
res += "*"
}
return res + t.Name()
}
L'appeler avec des valeurs:
tst4 := Ab{}
tst5 := new(Ab)
tst6 := &tst5 // type of **Ab
tst7 := &tst6 // type of ***Ab
Sortie (essayez-le sur Go Playground ):
Ab
*Ab
**Ab
***Ab
Type.String()
Une approche plus simple et meilleure consisterait à utiliser Type.String()
au lieu de Type.Name()
qui gère automatiquement les pointeurs et inclut également le nom du package. Par exemple.:
func getType(myvar interface{}) string {
return reflect.TypeOf(myvar).String()
}
Pour l'exemple modifié, il génère:
string
int
float64
main.Ab
*main.Ab
Essayez cette variante sur le Go Playground .
fmt a un cool %T
tag également
package main
import (
"fmt"
"net/http"
)
type Potato struct {
}
func main() {
fmt.Printf("I have a %T, an %T and a %T\n", Potato{}, http.StatusMultipleChoices, &http.Response{})
}
les sorties I have a main.Potato, an int and a *http.Response
https://play.golang.org/p/6z7_0BSitm
Le problème est que new
renvoie un pointeur, ce qui suit devrait obtenir le résultat souhaité.
package main
import (
"fmt"
"reflect"
)
type Ab struct {
}
func getType(myvar interface{}) {
valueOf := reflect.ValueOf(myvar)
if valueOf.Type().Kind() == reflect.Ptr {
fmt.Println(reflect.Indirect(valueOf).Type().Name())
} else {
fmt.Println(valueOf.Type().Name())
}
}
func main() {
fmt.Println("Hello, playground")
tst := "string"
tst2 := 10
tst3 := 1.2
tst4 := new(Ab)
getType(tst)
getType(tst2)
getType(tst3)
getType(tst4)
}
La sortie est
Hello, playground
string
int
float64
Ab