英文:
Pass struct for function that accepts a interface
问题
我有以下代码:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
func AcceptInterface(i *MyInterface){
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
我原本期望这段代码能够正常工作,因为MyType
实现了MyInterface
接口,但是我得到了以下错误信息:
无法将
object
(类型为*MyType
)作为AcceptInterface
的参数,因为*MyInterface
是指向接口的指针,而不是接口本身。
我尝试使用类型断言:object.(MyInterface)
,但也不起作用。
我该如何解决这个问题?
英文:
I have the following code:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
func AcceptInterface(i *MyInterface){
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
I was expecting this to work, because MyType implements MyInterface, but I get:
> cannot use object (type *MyType) as type *MyInterface in argument to
> AcceptInterface: *MyInterface is pointer to interface, not interface
I tried doing type assertion: object.(MyInterface), but that doesn't work either.
How can I accomplish this?
答案1
得分: 15
根据错误提示,它说:
> 无法将对象(类型 *MyType)作为参数传递给 AcceptInterface 函数中的 *MyInterface 类型:*MyInterface 是指向接口的指针,而不是接口本身。
这意味着它期望的是一个 interface
值,而不是一个指针。
如果你在代码中将指针改为值(删除 &
和 *
),程序将不会出现错误:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
func AcceptInterface(i MyInterface){
}
func main() {
object := MyType{}
AcceptInterface(object)
}
编辑 1
如果你仍然想要使用指针作为参数,有两个关键的 Go 语言部分需要注意:
-
根据Go 语言规范,关于什么样的变量适合一个实例:
> 接口类型的变量可以存储任何具有方法集的类型的值,该方法集是接口的任何超集。
-
根据Go 语言规范,关于指针自动解引用:
> 与选择器一样,使用指针引用一个具有值接收器的非接口方法将自动解引用该指针:
pt.Mv
等同于(*pt).Mv
[和] 与方法调用一样,使用可寻址值引用具有指针接收器的非接口方法将自动取该值的地址:t.Mp
等同于(&t).Mp.
这两点很重要,因为它们结合起来解释了_指针变量仍然可以适合实例_。这是因为指针的方法集会被 Go 编译器自动解引用_(并且由于它所引用的变量可以适合一个实例,指针也可以适合)_!
实际上,这意味着为了判断一个指针是否适合一个实例,你必须将实例声明为_值_,将指针声明为_指针_。
如果你运行以下代码:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test() {}
func AcceptInterface(i MyInterface) {
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
你将看到没有错误!注意 object
声明中有一个 &
,但是 i
声明中没有 *
。
英文:
As the error says,
> cannot use object (type *MyType) as type *MyInterface in argument to AcceptInterface: *MyInterface is pointer to interface, not interface
This means that it is expecting an interface
value, not a pointer.
If you change the pointers to values in your code (by removing the &
and *
), the program will run with no errors:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
func AcceptInterface(i MyInterface){
}
func main() {
object := MyType{}
AcceptInterface(object)
}
Edit 1
If you still want to use a pointer as an argument, there are two important parts of the Go language to note
-
From the Go Spec on what exacly is a variable that fits an instance:
> A variable of interface type can store a value of any type with a method set that is any superset of the interface.
-
From the Go Spec on what pointers being automatically dereferenced:
> As with selectors, a reference to a non-interface method with a value receiver using a pointer will automatically dereference that pointer:
pt.Mv
is equivalent to(*pt).Mv
[and] as with method calls, a reference to a non-interface method with a pointer receiver using an addressable value will automatically take the address of that value:t.Mp
is equivalent to(&t).Mp.
Those two points are important, because when combined they explain that pointers to variables can still fit instances. This is because the pointer's method set is automatically dereferenced by the Go compiler (and since the variable it is referencing can fit an instance, the pointer can, too)!
In action, this means that in order to see if a pointer fits an instance, you have to declare the instance as a value and the pointer as a pointer.
If you run this code:
package main
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test() {}
func AcceptInterface(i MyInterface) {
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
you will see that there are no errors! Notice how there is an &
in the object
declaration, but no *
in the i
declaration?
答案2
得分: 0
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
// 注意:这意味着 `MyType` 实现了接口 `MyInterface`,而不是 `MyType*`。
你可以使用:
func (m *MyType) Test(){} // 注意这里
func AcceptInterface(i *MyInterface){
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
英文:
type MyInterface interface {
Test()
}
type MyType struct {
}
func (m MyType) Test(){}
Note: it means that MyType
implemts the interface MyInterface
, not MyType*
.
You can use:
func (m *MyType) Test(){} //Notice here
func AcceptInterface(i *MyInterface){
}
func main() {
object := &MyType{}
AcceptInterface(object)
}
答案3
得分: 0
如果你想传递一个指向接口的指针,请使用显式类型转换:
func main() {
var object MyInterface = MyType{}
AcceptInterface(&object)
}
我不建议使用指针接口,因为你需要编写类似(*i).Test()
这样的代码来调用接口指针的方法。编译器会自动对结构体指针进行解引用,但对于接口指针则不会这样做。
英文:
Use explicit typing if you want to pass a pointer to interface:
func main() {
var object MyInterface = MyType{}
AcceptInterface(&object)
}
I would not recommend using pointer interfaces as you would need to write code like (*i).Test()
to call the interface pointer methods. The compiler do auto dereferencing for struct pointers, not so for interface pointers.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论