我正在使用指针接收器学习接口,类型转换和方法。 指针接收器方法背后的规则和术语让我感到困惑。 让我向一个程序表明我的困惑。
这是我的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)
如何修复该行代码,以便我能够调用该方法 指针接收器?请解释一个解决方案,并澄清为什么会这样 通过使用指针接收器设置方法的概念不起作用。
答案 0 :(得分:4)
您不能(在这种情况下隐含地用于指针接收器)获取表达式(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.
The Go Programming Language Specification
对于接口类型的表达式x和类型T,表示主要的 表达
x.(T)
断言x不是nil,并且存储在x中的值是T类型。 符号x。(T)称为类型断言。
如果类型断言成立,则表达式的值为值 存储在x中,其类型为T.如果类型断言为false,则a 发生运行时恐慌。
方法调用x.m()在方法集(类型)x时有效 包含m,参数列表可以分配给参数列表 米如果x是可寻址的并且& x的方法集包含m,则x.m()是 (& x).m()
的简写对于类型为T的操作数x,地址操作& x生成a 类型* T到x的指针。操作数必须是可寻址的,即 变量,指针间接或切片索引操作; 或可寻址结构操作数的字段选择器;或数组 可寻址数组的索引操作。作为例外 可寻址性要求,x也可以是(可能括在括号中) 复合文字。
类型断言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)
答案 1 :(得分:-2)
修复将是:
var b interface{} = &Employee{"Bob"}
b.(*Employee).Hello()
这里的b是一个实际上是“指向Employee的指针”的接口,然后是类型断言的接口。要记住的是“员工”和“员工指针”是两种不同的类型。