简体   繁体   中英

How do I use reflect to check if the type of a struct field is interface{}?

I am using the reflect package to determine the type of a struct field is interface{}

I want to do the comparison like so (where t is a reflect.Type ):

if  t == reflect.TypeOf(interface{}) {

}

The problem is that the compiler complains: type interface {} is not an expression .

Is there anyway to check if the type of a struct field is an interface{} ?

You can get the type of the interface Y by creating a nil instance and using reflection:

yType := reflect.TypeOf((*Y)(nil)).Elem()

and then use the expression

reflect.TypeOf(x).Implements(yType)

to check if the type implements the interface.

Interfaces themselves can not be instantiated. The interface{} interface which is the empty interface is implemented by all types so all fields implement that.

https://play.golang.org/p/gRfheIW_9Y

Actually it also works with the empty interface{} itself but this will always return true (if i'm not missing something):

https://play.golang.org/p/29rWP4LtIo

interface{} is a type, and reflect.TypeOf() expects a value. So you can't pass the literal interface{} to it. You can only pass a value.

Back to the original question. Let's see a struct example:

type My struct {
    A int
    B interface{}
    C io.Reader
}

You want to tell if the type of a field is interface{} . Acquire the reflect.Type of the struct type, then you can access the fields using Type.Field() or Type.FieldByName() .

This gives you a value of type reflect.StructField which stores the type of the field.

So far so good. But what should we compare it to? interface{} is an interface type with 0 methods. You can't have (instantiate) a value of that type. You can only have values of concrete types, but yes, they may be wrapped in an interface type.

You could use Type.Kind , and compare it to reflect.Interface , which tells you if it's an interface, but this is true for all interface types. You could also check if it has 0 methods with Type.NumMethod() , which must be 0 for interface{} , but other interfaces could also have 0 methods...

You may use Type.Name , but since interface{} is a unnamed type, its name is the empty string "" (and there are other unnamed types). You may use Type.String() which returns "interface {}" for the empty interface:

t := reflect.TypeOf(My{})

for i := 0; i < t.NumField(); i++ {
    f := t.Field(i)
    fmt.Printf("Field %q, type: %-12v, type name: %-8q, is interface{}: %v\n",
        f.Name, f.Type,
        f.Type.Name(),
        f.Type.String() == "interface {}",
    )
}

Output (try it on the Go Playground ):

Field "A", type: int         , type name: "int"   , is interface{}: false
Field "B", type: interface {}, type name: ""      , is interface{}: true
Field "C", type: io.Reader   , type name: "Reader", is interface{}: false

You might find this related question interesting / useful: Identify non builtin-types using reflect

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM