英文:
Go error: "embedded type cannot be a pointer to interface"
问题
以下代码会在编译时出现错误:
type IFile interface {
Read() (n int, err error)
Write() (n int, err error)
}
type TestFile struct {
*IFile
}
错误信息:
./test.go:18: 嵌入类型不能是接口的指针
为什么不能嵌入 *IFile
?
英文:
The following code gives compile-time error:
type IFile interface {
Read() (n int, err error)
Write() (n int, err error)
}
type TestFile struct {
*IFile
}
Error:
> ./test.go:18: embedded type cannot be a pointer to interface
Why can't I embed *IFile
?
答案1
得分: 4
语言规范不允许这样做。规范中相关的部分是:结构类型:
声明了类型但没有显式字段名的字段是_匿名_字段,也称为_嵌入_字段或将类型嵌入结构中。嵌入类型必须指定为类型名
T
或非接口指针类型名*T
,而T
本身不能是指针类型。未限定的类型名充当字段名。
指向接口类型的指针很少有用,因为接口类型可以保存指针或非指针值。
话虽如此,如果实现了你的IFile
类型的具体类型是指针类型,那么指针值将被包装在类型为IFile
的接口值中,所以你仍然需要嵌入IFile
,只是实现IFile
的值将是指针值,例如:
// 假设*FileImpl实现了IFile:
f := TestFile{IFile: &FileImpl{}}
**编辑:**回答你的评论:
首先,这是Go语言,不是C++。在Go语言中,接口不是指针,而是表示为(type;value)
的一对值,其中"value"可以是指针或非指针。更多信息请参阅博文:反射定律:接口的表示方式。
其次,如果FileImpl
是一个类型,f := TestFile{IFile : &FileIml}
显然是一个编译时错误,你需要一个*FileImpl
的值,而&FileImpl
显然不是。你需要使用复合字面量,形式为&FileImpl{}
,所以应该按照我上面发布的方式。
英文:
The language spec does not allow it. Relevant section from the spec: Struct types:
> A field declared with a type but no explicit field name is an anonymous field, also called an embedded field or an embedding of the type in the struct. An embedded type must be specified as a type name T
or as a pointer to a non-interface type name *T
, and T
itself may not be a pointer type. The unqualified type name acts as the field name.
A pointer to an interface type is very rarely useful, as an interface type may hold a pointer or a non-pointer value.
Having said that, if a concrete type that implements your IFile
type is a pointer type, then a pointer value will be wrapped in an interface value of type IFile
, so you still have to embed IFile
, just the value that implements IFile
will be a pointer value, e.g.
// Let's say *FileImpl implements IFile:
f := TestFile{IFile: &FileImpl{}}
Edit: Answer to your comment:
First, this is Go, not C++. In Go, interfaces are not pointers, but they are represented as a pair of (type;value)
, where "value" may be pointer or non-pointer. More about this in blog post: The Laws of Reflection: The representation of an interface.
Second, if FileImpl
is a type, f := TestFile{IFile : &FileIml}
is obviously a compile-time error, you need a value of *FileImpl
and &FileImpl
clearly isn't. You need for example a composite literal which is in the form of &FileImpl{}
, so it should be as I posted above.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论