I found this question with this great answers:
How to find a type of a object in Golang?
I played around with the answer and tried to get the name of a struct 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 playground: http://play.golang.org/p/tD8mygvETH
But the output is:
Hello, playground string int float64 Program exited.
Expected output would be:
Hello, playground string int float64 Ab Program exited.
I tried to figure out by reading the documentation but didn't find the issue about that. So, sorry for the very general question, but:
What's the reason, reflect.TypeOf().Name()
does not work with (this) struct(s)?
You should avoid reflection. Some packages (e.g. fmt) cannot be implemented without reflection as you cannot typeswitch on all existing and upcoming types. If you are new to Go: Keep away from reflection.
Reflection in Go is a form of metaprogramming. Reflection allows us to examine types at runtime. It also provides the ability to examine, modify, and create variables, functions, and structs at runtime. The Go reflect package gives you features to inspect and manipulate an object at runtime.
The reflect. Indirect() Function in Golang is used to get the value that v points to, i.e., If v is a nil pointer, Indirect returns a zero Value. If v is not a pointer, Indirect returns v. To access this function, one needs to imports the reflect package in the program.
In your example you pass a value of pointer type (*Ab
), not a struct type.
Type.Name()
If it is not a pointer, Type.Name()
will properly return Ab
. In case of pointer if you still want the struct's name, you can use Type.Elem()
to get the element's type:
func getType(myvar interface{}) string { if t := reflect.TypeOf(myvar); t.Kind() == reflect.Ptr { return "*" + t.Elem().Name() } else { return t.Name() } }
Testing it:
tst4 := Ab{} tst5 := new(Ab) fmt.Println(getType(tst4)) fmt.Println(getType(tst5))
Output (try your modified example on the Go Playground):
Ab *Ab
Note:
Note that as Type.Name()
does not resolve pointers, it would not work if the value passed is a pointer to pointer, e.g. **Ab
, while as Type.String()
automatically resolves pointers, would work in this case too.
We can easily make our getType()
function to work with **Ab
too (or with any depth of pointers):
func getType(myvar interface{}) (res string) { t := reflect.TypeOf(myvar) for t.Kind() == reflect.Ptr { t = t.Elem() res += "*" } return res + t.Name() }
Calling it with values:
tst4 := Ab{} tst5 := new(Ab) tst6 := &tst5 // type of **Ab tst7 := &tst6 // type of ***Ab
Output (try it on the Go Playground):
Ab *Ab **Ab ***Ab
Type.String()
A simpler and better approach would be to use Type.String()
instead of Type.Name()
which automatically handles pointers and also includes package name. E.g.:
func getType(myvar interface{}) string { return reflect.TypeOf(myvar).String() }
For the modified example it outputs:
string int float64 main.Ab *main.Ab
Try this variant on the Go Playground.
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\n", Potato{}, http.StatusMultipleChoices, &http.Response{}) }
outputs I have a main.Potato, an int and a *http.Response
https://play.golang.org/p/6z7_0BSitm
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With