使用reflect.Typeof()的golang类型断言

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
", item)
    item2 := i.(reflect.TypeOf(i))  // reflect.TypeOf(i) is not a type
    fmt.Printf("Hello, item2 : %v
", item2)

}

I think what you're looking for here is a type switch. https://tour.golang.org/methods/16

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:

  1. At compile time: It causes the resulting expression to have the desired compile-time type. The expression x.(T) has compile-time type T. This allows you to do stuff the expression that you can do with type T, which you may not be able to do with the type of x.
  2. 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 you can use ValueOf to solve this

item2 :=  reflect.ValueOf(i)
fmt.Printf("Hello, item2 : %v
", item2)

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