1. package main
    2. import (
    3. "fmt"
    4. )
    5. type Heap []int
    6. func (h Heap) swap() {
    7. h[0], h[1] = h[1], h[0]
    8. fmt.Printf("数组 %p \n", h)
    9. fmt.Printf("结构体 %p \n", &h)
    10. h = append(h, []int{4, 5, 6}...)
    11. fmt.Printf("扩容后数组 %p \n", h)
    12. fmt.Printf("扩容后结构体 %p \n", &h)
    13. }
    14. func main() {
    15. arrSlice := make([]int, 5)
    16. fmt.Printf("切片数组地址 the pointer is : %p \n", arrSlice)
    17. fmt.Printf("切片结构体地址 the pointer is : %p \n", &arrSlice) //这是arrSlice本身的指针,也就是结构体的指针
    18. printPointer(arrSlice)
    19. a := Heap{1, 2, 3}
    20. fmt.Printf("数组 %p \n", a)
    21. fmt.Printf("结构体 %p \n", &a)
    22. a.swap()
    23. fmt.Println(a)
    24. }
    25. func printPointer(any interface{}) {
    26. fmt.Printf("传进去以后切片数组地址 the pointer is : %p \n", any)
    27. fmt.Printf("传进去以后切片结构体地址 the pointer is : %p \n", &any) //打印传过来的结构体arrSlice的指针
    28. }

    运行结果

    1. go run 1.go
    2. 切片数组地址 the pointer is : 0xc0000ac030
    3. 切片结构体地址 the pointer is : 0xc0000a6018
    4. 传进去以后切片数组地址 the pointer is : 0xc0000ac030
    5. 传进去以后切片结构体地址 the pointer is : 0xc000096220
    6. 数组 0xc0000b0018
    7. 结构体 0xc0000a6060
    8. 数组 0xc0000b0018
    9. 结构体 0xc0000a6090
    10. 扩容后数组 0xc0000ac090 //创建了新的底层数组
    11. 扩容后结构体 0xc0000a6090 //此处为指针的拷贝,函数外的切片仍指向原数组的地址
    12. [2 1 3]

    如果是用指针作为接收者,那么变量(结构体对象)本身是可以修改的,因为指针传递的是变量的地址,因此变量内部的数据可以修改。
    如果用值作为接收者,那么对象内部的数据无法修改,因为用值作为接收者,在调用方法时,传递进去的是对象的副本,即使修改也只是修改副本的值,原对象的数据不会发生改变。这种可以理解为对象在该方法内是只读的。

    当传入一个切片时,实际上传入的是切片的拷贝,也就是底层数组指针的拷贝。所以可以实现切片中元素位置的交换,因为交换元素不会触发扩容,不会创建新的数组。但是如果在函数内部增加切片的元素导致扩容,会创建新的底层数组,然而函数外面的指针指向的仍然是原来数组的地址,因此修改无效。