Go:接口方法调用

Go:接口方法调用,go,Go,下面的代码中有两个关于Go接口的问题 type Color interface { getColor() string setColor(string) } type Car struct { color string } func (c Car) getColor() string { return c.color } func (c Car) setColor(s string) { c.color = s } func main() {

下面的代码中有两个关于Go接口的问题

type Color interface {
    getColor() string
    setColor(string)
}

type Car struct {
    color string
}
func (c Car) getColor() string {
    return c.color
}
func (c Car) setColor(s string) {
    c.color = s
}

func main() {
    car := Car{"white"}
    col := Color(car)

    car = col.(Car)         // L(1)
    car.setColor("yellow")
    fmt.Println(col)        // L(2)
    fmt.Println(car)
    car.color = "black"
    fmt.Println(col)        // L(3)
    fmt.Println(car)
}
问题1:可以将
L(1)写为“car,\:=col.(car)”?

Q2:
L(2)
打印“白色”而不是“黄色”

为什么<代码>L(3)似乎正确打印“黑色”


谢谢。

为了让setColor变异Car对象,您需要传递指针,您的代码按值传递Car,并更改该值的颜色,然后在方法返回时立即丢弃Car值的副本

已更改,以便通过指向Car的指针满足接口要求

func (c *Car) getColor() string {
    return c.color
}
func (c *Car) setColor(s string) {
    c.color = s
}
上述链接输出:

&{yellow}
&{yellow}
&{black}
&{black}
问题1:

不,你不能说car。原因并不十分明显。以下是L1中的OK语句列表:

car,ok := col.(Car)
car = col.(Car)
car,_ = col.(Car)
_,ok := col.(Car)
“:=”是声明/赋值的缩写形式,因为car已在该范围内声明,:=将给您一个错误(“在:=”的左侧没有新变量”)。将“ok”放在那里声明一个新变量(“ok”),但是,下划线/忽略伪变量不算作新变量,因为:=

编辑:为了清楚起见,您可以在此处放置“ok”或下划线,因为类型断言同时返回类型断言值和指示断言是否成功的布尔值。如果问题实际上是关于“u”的一般情况,而不是关于“:”=“操作员:不,在一般情况下,您不能执行以下操作

a,_ := 5
因为该语句只返回一个值,go不会让您忽略任何内容。(您将得到错误:“分配计数不匹配2=1”)

问题2:

在Go中,方法可以是指针或值/基类型。我相信你会发现以下方法很好:

car.setColor("yellow")
//...
func (car Car) setColor(s string) {
    car.color = s
    fmt.Println(car.color)
}
在此代码中,它将正确打印“黄色”。这是因为您正在按值传递方法receiver。事实上,它确实修改了汽车——但与你经过的汽车不同,一辆恰好是你调用该方法的汽车的完美复制品的汽车。要解决这个问题,您需要一个指针接收器

func (car *Car) setColor(s string) {
    car.color = s
}
这将使更改在调用后可见,因为您为方法提供了汽车所在的位置,而不仅仅是它拥有的数据。更详细地说,有少数情况涉及“引用类型”(映射、切片、通道),在这些情况下,您可以看到非指针方法之外的副作用,但这些都是规则的例外

请注意,如果给这个方法一个指针接收器,Car类型的变量将不再实现接口颜色。相反,实现接口的类型是*Car(指向汽车的指针)。事实上,由于指针在Go中是透明的,即使您将getColor留给非指针接收器,这也是正确的,但通常更好的形式是使类型上的所有方法在指针或基类型上实现接口,而不是两者的混合


一个杂项说明,因为你似乎正在学习:本质上,setColor和getColor的开头都是小写字母,没有什么错。但是,请注意,在您正在编写的即时包之外,这些方法将不可用。要使它们可见,它们必须以大写字母开头。

setColor
并不像您想象的那样。你应该让
c
(接收器)成为指向汽车的指针。