英文:
How do I use reflect to check if the type of a struct field is interface{}?
问题
我正在使用reflect包来确定一个结构体字段的类型是否为interface{}
。
我想要进行如下的比较(其中t
是一个reflect.Type
):
if t == reflect.TypeOf(interface{}) {
}
问题是编译器报错:type interface {} is not an expression
。
有没有办法检查结构体字段的类型是否为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{}
?
答案1
得分: 7
你可以通过创建一个空实例并使用反射来获取接口Y
的类型:
yType := reflect.TypeOf((*Y)(nil)).Elem()
然后使用表达式
reflect.TypeOf(x).Implements(yType)
来检查类型是否实现了该接口。
接口本身不能被实例化。空接口interface{}
被所有类型实现,因此所有字段都实现了它。
实际上,你也可以使用空接口interface{}
本身,但这将始终返回true
(如果我没有漏掉什么的话):
https://play.golang.org/p/29rWP4LtIo
英文:
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):
答案2
得分: 5
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{}
是一个没有方法的接口类型。你不能拥有(实例化)该类型的值。你只能拥有具体类型的值,但是是可以包装在接口类型中的。
你可以使用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
你可能会发现这个相关问题有趣/有用:https://stackoverflow.com/questions/36310538/identify-non-builtin-types-using-reflect/37292523#37292523
英文:
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: https://stackoverflow.com/questions/36310538/identify-non-builtin-types-using-reflect/37292523#37292523
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论