我们很容易区分和编写值接收方法指针接收方法
func (u User) notify(){
fmt.Println(u.Name)
u.Name = "liming"
}
func (uptr *User) notity(){
fmt.Println(uptr.Name)
uptr.Name = "liming"
}
一个很容易理解的地方是,值接收方法在调用时,传递的是值的副本,一般来说,修改副本不影响其原值
而指针接收方法传递是指针,会影响,这点和其函数传参是一样的。
方法集的规范说的非常清楚。
而在调用的规则中,go做了一些改变:
- 两种类型及其方法可以交叉调用,此时隐含有解引用和取指针操作
- 会不会改变是其方法定义改变的。比如指针调用值方法,会首先解应用得到其值,让后复制值,使用副本调用
- 有时候值不能寻址,那么值就无法调用指针接收者方法,在编译期会报错。
接口类型判断
正因为第三条的原因,指针接收者方法不在值类型的方法集中。当想把一个对象当成一个接口使用时,就要判断
其方法集是否包含接口的方法集,否则就不是该接口类型
- 内部类型会被提升至外部
- 如果有相同标识符,外部会直接覆盖内部
- 覆盖后,任然可以通过内部值去访问
- 数组的使用很简单,在初始化时长度就固定了
array :=[...]int{21,12,12,34} // 自动计算长度
-
数组在golang中是值类型,意味着赋值时是副本,函数调用时传递的是副本,同时数组赋值的条件很苛刻,
类型和长度一样,这限制了其使用,改为使用切片。多维数组也是传递副本,for语句也是副本 -
应为golang中数组很鸡肋,其切片类似于c/c++中的数组,同时又有python中角标的切割方式,比较方便。
要说明的是,slice存在很多共享内存的情况,有些情况问题很难排查,也不安全,同时for语句也是副本。 -
面对共享内存的不安全性,如何处理呢?合理使用append函数,append的函数会在len(sli) == cap(sli)时,
重新分配底层数组,这样就和原数组分离了。
参考博客:
值接受方法和指针接收方法
Golang:一文搞懂string, unicode, utf-8, 以及rune
Golan中的数据容器