我正在学习接口(interface),类型转换和带有指针接收器的方法。
指针接收器方法背后的规则和术语使我感到困惑。
让我展示我对一个程序的困惑。

这是我的Go程序。

package main

import "fmt"

type Employee struct {
    Name string
}

func (e Employee) Hi() {
    fmt.Printf("Hi! I am %s.\n", e.Name)
}

func (e *Employee) Hello() {
    fmt.Printf("Hello! I am %s.\n", e.Name)
}

func main() {
    var a Employee = Employee{"Alice"}
    a.Hi()
    a.Hello()

    var b interface{} = Employee{"Bob"}
    b.(Employee).Hi()
    // b.(Employee).Hello()
}

这是输出。
Hi! I am Alice.
Hello! I am Alice.
Hi! I am Bob.

如果删除最后注释的行,则会出现此错误。
# command-line-arguments
./foo.go:24: cannot call pointer method on b.(Employee)
./foo.go:24: cannot take the address of b.(Employee)

如何修复该行代码,以便能够使用
指针接收器?请解释一个解决方案,并说明原因
通过使用指针接收器放下方法的概念无法正常工作。

最佳答案

您不能(在这种情况下,对于指针接收器来说是隐式的)获取表达式结果的地址(b.(Employee))。您可以获取变量的地址。例如,

package main

import "fmt"

type Employee struct {
    Name string
}

func (e Employee) Hi() {
    fmt.Printf("Hi! I am %s.\n", e.Name)
}

func (e *Employee) Hello() {
    fmt.Printf("Hello! I am %s.\n", e.Name)
}

func main() {
    var a Employee = Employee{"Alice"}
    a.Hi()
    a.Hello()

    var b interface{} = Employee{"Bob"}
    b.(Employee).Hi()
    // b.(Employee).Hello()
    // main.go:24: cannot call pointer method on b.(Employee)
    // main.go:24: cannot take the address of b.(Employee)
    e := b.(Employee)  // e, a variable, is addressable
    e.Hello()

    var c interface{} = &Employee{"Chris"}
    c.(*Employee).Hi()
    c.(*Employee).Hello()
}

输出:
Hi! I am Alice.
Hello! I am Alice.
Hi! I am Bob.
Hello! I am Bob.
Hi! I am Chris.
Hello! I am Chris.



断言b.(Employee)类型的值是Employee类型。方法调用b.(Employee).Hello()(&b.(Employee)).Hello()的简写,因为func (e *Employee) Hello()具有指针接收器。但是,表达式b.(Employee)是不可寻址的。所以,
error: cannot call pointer method on b.(Employee)
error: cannot take the address of b.(Employee)

关于pointers - 类型断言后如何使用指针接收器调用方法?,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/43883502/

10-11 22:10