Golang: 值类型&引用类型坑(12)

别再说传引用还是传值了,在 Golang 里面应该先搞清楚这个东西的类型是什么。

专栏的介绍可以参考 《GotchaGolang专栏》,代码可以看《宝库-Gotcha》

透过现象看本质。我们当初在 C/C++ 中折腾指针啊,引用啊,不就是为了能否修改原来的变量么

Golang 直接指针问题的核心,用类型本身的性质解决了该问题;而不是过多的把注意力放在参数传递上

  • 值类型? — 包括基本类型,数组,自定义类型struct, 只有传递指针才能更改其原来内存的内容,否则值传递只能是拷贝
  • 引用类型? — 包括 slice, map, chan, func,这里本身就是引用类型, 即便是值传递也可以更改原来的内容(但是内部和外部的地址不同)

举个例子吧: 自定义的 type, struct

1
2
3
4
5
6
7
func (u user) fun1() {
....
}

func (u *user) fun2() {
....
}

Value receiver操作的是值的拷贝,而pointer receiver操作的是实际的值。

用pointer去调用value receiver的方法,实际的操作是: (*p).fun1()
而用value去调用pointer receiver的方法,实际的操作是:(&v).fun2()

对于引用类型,就不要,也不需要去使用其指针了,直接拿到实例就可以了,一般是 make 返回的,内部实现返回的其实是指针。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

//make map
// makemap implements a Go map creation make(map[k]v, hint)
// If the compiler has determined that the map or the first bucket
// can be created on the stack, h and/or bucket may be non-nil.
// If h != nil, the map can be created directly in h.
// If bucket != nil, bucket can be used as the first bucket.
func makemap(t *maptype, hint int64, h *hmap, bucket unsafe.Pointer) *hmap {
//...
}

//make chan
func makechan(t *chantype, size int64) *hchan {
//...
}

搞清楚是引用类型,还是值类型;再决定是传递指针,还是传递引用

因为可以看到引用类型本身相关的方法已经做了封装,不需要再额外传递指针了。

但是不管哪种类型,只要是值传递,那么调用内部和外部,相关参数的地址肯定不一样,值传递就是拷贝啊,都是副本(即便是引用类型,也是副本;可以比较内外引用变量的地址)。但是决定能够修改原来的变量与否,还在于传递的变量本身是值类型,还是引用类型。

透过现象看本质。我们当初在 C/C++ 中折腾指针啊,引用啊,不就是为了能否修改原来的变量么

Golang 直指指针问题的核心,用类型本身的性质解决了该问题;而不是过多的把注意力放在参数传递上


Merlin 2018.3 参数本身的坑,核心且关键

文章目录
|