I've tried to identify a struct with string value(name).
reflect.TypeOf
returns Type
.
But type assertion needs a type
.
How can I casting Type
to type
?
Or any suggestion to handle it?
http://play.golang.org/p/3PJG3YxIyf
package main
import (
"fmt"
"reflect"
)
type Article struct {
Id int64 `json:"id"`
Title string `json:"title",sql:"size:255"`
Content string `json:"content"`
}
func IdentifyItemType(name string) interface{} {
var item interface{}
switch name {
default:
item = Article{}
}
return item
}
func main() {
i := IdentifyItemType("name")
item := i.(Article)
fmt.Printf("Hello, item : %v\n", item)
item2 := i.(reflect.TypeOf(i)) // reflect.TypeOf(i) is not a type
fmt.Printf("Hello, item2 : %v\n", item2)
}
A type assertion, syntactically, takes a type in the parentheses, not an expression. So it is a syntax error.
You seem to be trying to do a type assertion with a value computed at runtime. Does that make sense? Let's think about what a type assertion is.
A type assertion consists of two things:
- At compile time: It causes the resulting expression to have the desired compile-time type. The expression
x.(T)
has compile-time typeT
. This allows you to do stuff the expression that you can do with typeT
, which you may not be able to do with the type ofx
. - At runtime: It checks whether the value is not
nil
and is actually of the given type, and if not, it causes a panic.
The first part obviously doesn't make sense for a type computed at runtime. The compile-time type of the resulting expression cannot depend on something that is not known at compile-time.
The second one (runtime check) can be done with a type computed at runtime. Something like:
if reflect.TypeOf(x) != someTypeComputedAtRuntime {
panic(42)
}
If you need to switch on the type of the outer interface{} you wont need reflection.
switch x.(type){
case int:
dosomething()
}
...but if you need to switch on the type of the attributes in an interface then you can do this:
s := reflect.ValueOf(x)
for i:=0; i<s.NumValues; i++{
switch s.Field(i).Interface().(type){
case int:
dosomething()
}
}
I haven't found a cleaner way, I'd love to know if it exists.
I think what you're looking for here is a type switch. https://tour.golang.org/methods/16
If you can handle the noise and implement an extra method which all the types implement e.g. 'Type() string', you can do something like this:
ve := &ValidationError{}
nf := &NotFound{}
switch err.Type() {
case ve.Type() :
SendBadRequest(w, err)
case nf.Type() :
http.NotFound(w, r)
default:
SendInternalError(w, err)
}
I think you can use ValueOf to solve this
item2 := reflect.ValueOf(i)
fmt.Printf("Hello, item2 : %v\n", item2)
来源:https://stackoverflow.com/questions/27900568/golang-type-assertion-using-reflect-typeof