GoLang大坑之接口的对象方法和指针方法
-
现在大多数语言都是面向对象语言,使用Java之后,尽管非常冗余,但是和c++一样逻辑清晰,没有什么大坑可以踩。但是GoLang注重简洁清晰,经常有莫名大坑出现,比如闭包等。
-
今天在公司写业务需求的时候,被这个bug坑了老久,呜呜呜~
GoLang接口的几种实现方式–自定义
1. 对象方法
GoLang中类方法分为对象方法和指针方法,分属于不同的方法集,指针可以调用所有方法,而对象只能调用对象方法
下面我们看一个栗子
type People interface {
FeedCat()
FeedDog()
}
type XiaoMing struct {
Name string
}
func (x XiaoMing) FeedCat() {
fmt.Printf("FeedCat: %p name=%v\n", &x, x.Name)
x.Name="小花"
}
func (x XiaoMing) FeedDog() {
fmt.Printf("FeedDog: %p name=%v\n", &x, x.Name)
}
func main() {
ming := XiaoMing{Name: "minxu"}
fmt.Printf("ming: %p name=%v\n", &ming, ming.Name)
ming.FeedCat()
ming.FeedDog()
}
输出:
ming: 0xc000010200 name=minxu
FeedCat: 0xc000010220 name=minxu
FeedDog: 0xc000010240 name=minxu
我们知道在GoLang中 一切都是值传递(强烈不建议将slice/map作为引用传递来理解,因为slice对象在被拷贝的时候,除了指向数组的指针没变,length和capacity都被拷贝了一份 可以理解为struct{length int,capacity int,ptr *int},所以必然是值传递),
那么为什么上面的对象的地址输出不一样呢?为什么明明在FeedCat中将x.Name改为"小花",后续打印的还是minxu呢?因为GoLang的对象方法调用会将对象拷贝一份,可以这么理解:
func (x XiaoMing) FeedCat() {}
|
| 值传递 将x拷贝了一份
V
func FeedCat(x XiaoMing) {}
2. 指针方法
根据以下demo可以看出,指针方法是不会拷贝对象本身的
type People interface {
FeedCat()
FeedDog()
}
type XiaoMing struct {
Name string
}
func (x *XiaoMing) FeedCat() {
fmt.Printf("FeedCat: %p name=%v\n", x, x.Name)
x.Name="小花"
}
func (x *XiaoMing) FeedDog() {
fmt.Printf("FeedDog: %p name=%v\n", x, x.Name)
}
func main() {
ming := &XiaoMing{Name: "minxu"}
fmt.Printf("ming: %p name=%v\n", ming, ming.Name)
ming.FeedCat()
ming.FeedDog()
}
输出:
ming: 0xc000010200 name=minxu
FeedCat: 0xc000010200 name=minxu
FeedDog: 0xc000010200 name=小花
总结
指针方法和对象方法分为不同的方法集挺容易理解的,但是这个拷贝就对c系很不友好,,,