先看关于struct方法 receiver 是对象还是指针的问题
type ISth interface {
getInfo() string
}
type Person struct {
Name string
}
func (p Person) getInfo() string { // 注:这里是对象
return p.Name
}
func main() {
var sth ISth
sth = Person{Name: "felix"} // 变量赋值是合法的
sth = &Person{Name: "felix"} // 指针赋值也同样合法
fmt.Println(sth)
}
如果 receiver是对象, 接口变量既可以是对象, 也可以是对象指针, 我猜想原因是指针变量也是.操作符,
另外要注意, 两次sth赋值后效果是不同的, 指针赋值并没有发生整个Person变量的值拷贝
func main() {
var sth ISth
p1 := &Person{Name: "p1"} // p1 值指针
p2 := Person{Name: "p2"} // p2 是对象
sth = p1 // sth 与 p1 指向同一片内存
p1.Name = "p1 is changed" // p1 的 Name 修改了
fmt.Println(sth.getInfo()) // sth 下的 Name 同样也修改了, 打印出 "p1 is changed"
sth = p2 // 整个p2对象发生了值拷贝, sth与p2代表的是两片内存
p2.Name = "p2 is changed" // 只是修改了p2对象的Name值
fmt.Println(sth.getInfo()) // sth 并没有被影响, 打印出 "p2"
}
但如果receiver是指针,那么接口变量只能是对象指针了, 对象赋值将会编译不过
type ISth interface {
getInfo() string
}
type Person struct {
Name string
}
func (p *Person) getInfo() string { // 注: 这里是指针
return p.Name
}
func main() {
var sth1, sth2 ISth
sth1 = &Person{Name: "felix"} // 可以
sth2 = Person{Name: "mary"} // 编译报错
fmt.Println(sth1, sth2)
}
个人理解通常情况下receiver是指针比较合理, 这样在定义interface变量时, 就可以直接使用变量, 并被赋值为struct的指针, 当interface 作为变量传参或变量间赋值时, 直接使用interface变量本身, 不需要在取地址用指针了