Using reflection in Go to get the name of the structure

I found this question with these wonderful answers:

How to find the type of object in the Golang?

I played with the answer and tried to get the structure name in the same way:

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)) } 

Go to the site: http://play.golang.org/p/tD8mygvETH

But the way out:

 Hello, playground string int float64 Program exited. 

Expected Result:

 Hello, playground string int float64 Ab Program exited. 

I tried to find out by reading the documentation, but did not find a question about this. So sorry for the most general question, but:

What is the reason, reflect.TypeOf().Name() does not work with (this) struct (s)?

+6
source share
3 answers

In your example, you are passing a pointer type value ( *Ab ), not a structure type.

Type.Name()

If this is not a pointer, Type.Name() will correctly return Ab . In the case of a pointer, if you still want the name of the structure, you can use Type.Elem() to get the type of the element:

 func getType(myvar interface{}) string { if t := reflect.TypeOf(myvar); t.Kind() == reflect.Ptr { return "*" + t.Elem().Name() } else { return t.Name() } } 

Testing:

 tst4 := Ab{} tst5 := new(Ab) fmt.Println(getType(tst4)) fmt.Println(getType(tst5)) 

Conclusion (try your modified Go Playground example):

 Ab *Ab 

Note:

Note that since Type.Name() does not allow pointers, this will not work if the passed value is a pointer to a pointer, for example. **Ab , while Type.String() automatically resolves pointers, will work in this case Type.String() .

We can easily get our getType() function to work with **Ab too (or with any pointer depth):

 func getType(myvar interface{}) (res string) { t := reflect.TypeOf(myvar) for t.Kind() == reflect.Ptr { t = t.Elem() res += "*" } return res + t.Name() } 

Call with values:

 tst4 := Ab{} tst5 := new(Ab) tst6 := &tst5 // type of **Ab tst7 := &tst6 // type of ***Ab 

Exit (try on the Go Playground ):

 Ab *Ab **Ab ***Ab 

Using Type.String()

A simpler and better approach would be to use Type.String() instead of Type.Name() , which automatically processes pointers and also includes the package name. For instance:.

 func getType(myvar interface{}) string { return reflect.TypeOf(myvar).String() } 

For a modified example, it outputs:

 string int float64 main.Ab *main.Ab 

Try this option on the Go Playground .

+10
source

fmt has a cool %T tag as well

 package main import ( "fmt" "net/http" ) type Potato struct { } func main() { fmt.Printf("I have a %T, an %T and a %T", Potato{}, http.StatusMultipleChoices, &http.Response{}) } 

outputs I have a main.Potato, an int and a *http.Response https://play.golang.org/p/6z7_0BSitm

+2
source

The new task returns a pointer, the next should get the desired result.

 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) } 

Output

 Hello, playground string int float64 Ab 
+1
source

All Articles