实验
1 2 3 4
| func (engine *Engine) Delims(left, right string) *Engine { engine.delims = render.Delims{Left: left, Right: right} return engine }
|
在golang
中,一个方法的接收者可以为指针或者非指针,那么这两种形式的区别是什么呢?
这里做了个实验
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25
| package main
import "fmt"
type Test struct { a int b int }
func (h Test) testA() { (*h).b = 666 }
func (h *Test) testB() { h.b = 999 }
func main() { t := Test{a: 1, b: 2} t.testA()
fmt.Println(t) t.testB() fmt.Println(t) }
|
输出:
可以发现:当接收者为指针时,我们可以通过方法改变该接收者的属性,非指针类型不能改变接收者属性
补充
对于切片
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23
| package main
import "fmt"
type Heap []int
func (h Heap) testA() { h[1] = 666 }
func (h *Heap) testB() { (*h)[1] = 999 }
func main() { heap := Heap{1, 2, 3, 4}
heap.testA() fmt.Println(heap)
heap.testB() fmt.Println(heap) }
|
当接收者为一个切片时,输出是什么呢?结果如下
可以发现,这里testA
仍然改变了切片的属性。
原因与golang
中切片的底层有关
切片的底层
一个切片是一个数组片段的描述。它包含了指向数组的指针,片段的长度, 和容量(片段的最大长度)。

可以发现,当传递切片本身就是用一个指针来引用指向的数组,所以可以使用这种方法改变切片的属性。
对于数组
当我们把Heap
类型改为数组时,可以发现结果又和当初的结构体差不多了,即接收者为非指针时不能更改值
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| package main
import "fmt"
type Heap [4]int
func (h Heap) testA() { h[1] = 666 }
func (h *Heap) testB() { (*h)[1] = 999 }
func main() { heap := Heap{1, 2, 3, 4}
heap.testA() fmt.Println(heap)
heap.testB() fmt.Println(heap) }
|
输出: