【问题标题】:How do I use reflect to check if the type of a struct field is interface{}?如何使用反射检查结构字段的类型是否为 interface{}?
【发布时间】:2017-01-17 10:27:10
【问题描述】:

我正在使用反射包来确定一个struct字段的类型是interface{}

我想像这样进行比较(其中treflect.Type):

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

}

问题是编译器报错:type interface {} is not an expression

是否有办法检查结构字段的类型是否为interface{}

【问题讨论】:

    标签: go reflection


    【解决方案1】:

    你可以通过创建一个nil实例并使用反射来获取接口Y的类型:

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

    然后使用表达式

    reflect.TypeOf(x).Implements(yType)
    

    检查类型是否实现了接口。

    接口本身不能被实例化。作为空接口的 interface{} 接口由所有类型实现,因此所有字段都实现。

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

    实际上它也适用于空接口{} 本身,但这将始终返回 true(如果我没有遗漏什么):

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

    【讨论】:

    • 如果 Y 是 interface{},我得到了错误:cannot call non-function Y (type interface {})
    【解决方案2】:

    interface{} 是一个类型,reflect.TypeOf() 需要一个值。所以你不能将文字 interface{} 传递给它。你只能传递一个值。

    回到原来的问题。让我们看一个struct 的例子:

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

    您想判断字段的类型是否为interface{}。获取struct类型的reflect.Type,则可以使用Type.Field()Type.FieldByName()访问字段。

    这会为您提供一个类型为 reflect.StructField 的值,用于存储字段的类型。

    到目前为止一切顺利。但是我们应该将它与什么进行比较? interface{} 是一个有 0 个方法的接口类型。您不能拥有(实例化)该类型的值。您只能拥有具体类型的值,但是可以,它们可以包装在接口类型中。

    您可以使用Type.Kind,并将其与reflect.Interface 进行比较,后者会告诉您它是否是一个接口,但这是所有接口类型的true。你也可以用Type.NumMethod()检查它是否有0个方法,interface{}必须为0,但其他接口也可以有0个方法...

    你可以使用Type.Name,但由于interface{}是一个未命名类型,它的名字是空字符串""(还有其他未命名的类型)。你可以使用Type.String(),它返回"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 {}",
        )
    }
    

    输出(在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
    

    您可能会发现这个相关问题很有趣/有用:Identify non builtin-types using reflect

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-08-25
      • 1970-01-01
      • 2012-01-15
      • 2017-07-06
      • 2018-09-10
      相关资源
      最近更新 更多