我正试图了解我在这里做错了..所有回复表示赞赏:)
如果取消注释“ // grow()”有效,
其他错误:
prog.go:38:2:不可能的类型切换情况:p(类型工厂)不能具有 动态类型plant1(增长方法具有指针接收器)prog.go:39:16: 不可能的类型断言:plant1不实现plant(增长 方法具有指针接收器)prog.go:40:2:不可能的类型切换 情况:p(植物类型)不能具有动态植物2(增长方法具有 指针接收器)prog.go:41:16:不可能的类型断言:plant2 不实现工厂(增长方法具有指针接收器) prog.go:60:12:不能在参数中使用p1(类型plant1)作为植物类型 以showHeight表示:plant1未实现plant(增长方法具有 指针接收器)prog.go:61:12:无法将p2(类型plant2)用作类型 在showHeight的参数中使用plant:plant2没有实现plant (增长方法具有指针接收器)
https://play.golang.org/p/oMv7LdW85yK
package main
import (
"fmt"
)
type plant1 struct {
name string
height int
}
type plant2 struct {
species string
height int
}
func (self *plant1) grow() {
self.height++
}
func (self *plant2) grow() {
self.height++
}
func (self plant1) getHeight() int {
return self.height
}
func (self plant2) getHeight() int {
return self.height
}
type plant interface {
getHeight() int
//grow()
}
func showHeight(p plant) {
switch p.(type) {
case plant1:
fmt.Println(p.(plant1).name, `Height = `, p.(plant1).getHeight())
case plant2:
fmt.Println(p.(plant2).species, `Height = `, p.(plant2).getHeight())
}
}
func main() {
p1 := plant1{
name: `Plant 10`,
height: 1,
}
p2 := plant2{
species: `Plant 20`,
height: 1,
}
p1.grow()
p1.grow()
p2.grow()
showHeight(p1)
showHeight(p2)
}
答案 0 :(得分:2)
包装到接口中的值不可寻址。该值必须是可寻址的,才能在指针接收器上调用方法。 grow
方法是使用指针接收器声明的。因此,编译器看到plant
类型和plant1
类型都没有实现plant2
接口。因此,您无法将plant1
或plant2
作为plant
传递给showHeight
函数。而且切换是不可能的,因为plant
接口的实现不包括plant1
和plant2
类型。
请参见Why value stored in an interface is not addressable in Golang
答案 1 :(得分:0)
您的函数func showHeight(p plant)
接受一个接口作为参数,而一个接口仅接受您实现的类型。
案例评论//grow()
自从您评论grow()
plant
以来,您仅为getHeight()
和plant 1
实现了一种方法plant 2
,一切顺利。
不加注释的grow()
现在您的所有类型(工厂1或工厂2)都没有实现plant
接口,因为grow()
是在*plant1
上定义的,而*plant2
不在plant1
上定义的,并且plant2
。结果;您的函数showHeight(p plant)
可以接受接口类型工厂,不能接受pl
,p2
,因为这些函数不再是plant
类型。
修复:
将指针传递为showHeight(&p1)
和showHeight(&p2)
,并在函数定义的情况和打印语句中,将plant1
和plant2
替换为*plant1
和{{1 }}
可能发生的混乱是,*plant2
和getHeight
尚未实现*plant1
,为什么*plant2
和*plant1
属于{{1 }}?
逻辑:传递指针时,可以从其中派生值以调用*plant2
,但是传递值时,不能派生任何地址来调用plant
旁注:getHeight
可以更改为grow()
,因为p是接口,它可以调用自己的方法。
答案 2 :(得分:0)
This due to the way the Method Set in Go works. In Go, a Method on a concrete receiver type implements both the value type and pointer type, while a method on a pointer receiver type implements only the pointer value.
In the case of the grow
method, the pointer receiver type *plant1/*plant2
are used, so only a pointer value of those types can implement the grow
method on an interface and the concrete value type can't.
Since the receiver type on getHeight
method is a concrete receiver type, it implements both the pointer type value (*plant1/*plant2
) and the type value of both plant
& plant2
.
If you change the parameter(p) passed to showHeight
to a *plant1/*plant2
type and change the type assertion to expect *plant1/*plant2
this would solve the error.
check this code example playground link