I want to retrieve back the type of value I saved once. I used reflect.Typeof() and saved the type. then try to use switch type. the type will always be "*reflect.rtype ". I couldn't retrieve either by type assertion.
package main
import (
"fmt"
"reflect"
)
func main() {
var alltypes []interface{}
alltypes = append(alltypes, reflect.TypeOf(true))
alltypes = append(alltypes, reflect.TypeOf(0.0))
alltypes = append(alltypes, reflect.TypeOf(0))
fmt.Printf("%T\t%q\n", alltypes, alltypes)
for _, v := range alltypes {
fmt.Printf("%T\t%q\n", v, v)
res, ok := v.(bool)
fmt.Println("res: ", res, " ok: ", ok)
switch v.(type) {
default:
fmt.Printf("unexpected type %T\n", v)
case bool:
fmt.Println("bool type!")
case int:
fmt.Println("int type!")
case float64:
fmt.Println("float64 type!")
}
}
}
Playground: https://play.golang.org/p/kqDo4DPYjra
A reflect.Type
holds no value you could type assert (actually you could, but that could only be reflect.Type
, not what you want). A reflect.Type
is just a type descriptor (which you obtained from a value).
However, you could create a value of the type represented by reflect.Type
, and you can type-assert the values from that you originally wanted.
To create a new pointer value, use reflect.New()
. To obtain the pointed value, use Value.Elem()
. These are all wrapped in a reflect.Value
. To unwrap it, use Value.Interface()
.
For example:
for _, v := range alltypes {
fmt.Printf("%T\t%q\n", v, v)
value := reflect.New(v.(reflect.Type)).Elem().Interface()
switch value.(type) {
default:
fmt.Printf("unexpected type %T\n", v)
case bool:
fmt.Println("bool type!")
case int:
fmt.Println("int type!")
case float64:
fmt.Println("float64 type!")
}
}
This will output (try it on the Go Playground):
[]interface {} ["bool" "float64" "int"]
*reflect.rtype "bool"
bool type!
*reflect.rtype "float64"
float64 type!
*reflect.rtype "int"
int type!
Also if you don't want to create new values just test the type, "save" the reflect.Type
descriptors of the types you're interested in, and use a normal switch
on the type:
var (
TypeBool = reflect.TypeOf(true)
TypeFloat64 = reflect.TypeOf(0.0)
TypeInt = reflect.TypeOf(0)
)
func main() {
var alltypes []interface{}
alltypes = append(alltypes, reflect.TypeOf(true))
alltypes = append(alltypes, reflect.TypeOf(0.0))
alltypes = append(alltypes, reflect.TypeOf(0))
fmt.Printf("%T\t%q\n", alltypes, alltypes)
for _, v := range alltypes {
fmt.Printf("%T\t%q\n", v, v)
switch v {
default:
fmt.Printf("unexpected type %T\n", v)
case TypeBool:
fmt.Println("bool type!")
case TypeInt:
fmt.Println("int type!")
case TypeFloat64:
fmt.Println("float64 type!")
}
}
}
This will output (try it on the Go Playground):
[]interface {} ["bool" "float64" "int"]
*reflect.rtype "bool"
bool type!
*reflect.rtype "float64"
float64 type!
*reflect.rtype "int"
int type!
Recommended reading: The Go Blog: The Laws of Reflection