1、我们先看一个数组案例,数组在内存的内存分配情况。
package main
import "fmt"
func main() {
// 数组的地址可以通过数组名来获取
// 数组的第一个元素的地址就是数组的地址
// 数组的各个元素的间隔是依据数组的类型决定的,比如int64间隔8个,int32间隔4个
var intArr [3]int
fmt.Println(intArr)
//fmt.Printf("未赋值之前的intArr地址=%p", intArr)
fmt.Println()
intArr[0] = 10
intArr[1] = 20
intArr[2] = 30
fmt.Printf("intArr的地址=%p int[0]地址=%p int[1]地址%p int[2]地址%p", &intArr, &intArr[0], &intArr[1], &intArr[2])
}
输出结果是:
intArr的地址=0xc0000141c8 int[0]地址=0xc0000141c8 int[1]地址0xc0000141d0 int[2]地址0xc0000141d8 这个这里看出,数组地址(绿色)就是第一个元素地址。由于我的系统是64位,int[0]与int[1]相差8个字节。
结论:数组是分配一段连续的内存空间。每个单元地址与下一个单元地址相差8个字节(32位是4个字节,与64位不同)
2、切片的形参传递与实参的影响
package main
import "fmt"
func change(a []int) {
a = append(a, 1, 2)
fmt.Printf("a的地址:%p |a的长度:%d |a的容量:%d\n", a, len(a), cap(a)) //a的地址:0xc00000c2c0 |a的长度:7 |a的容量:8
fmt.Printf("a的值:%v\n", a) //a的值:[0 0 0 0 0 1 2]
}
func main() {
s := make([]int, 5, 8)
fmt.Printf("s的地址:%p |s的长度:%d |s的容量:%d\n", s, len(s), cap(s)) //s的地址:0xc00000c2c0 |s的长度:5 |s的容量:8
fmt.Printf("切片s的值:%v\n", s) //切片s的值:[0 0 0 0 0]
change(s)
s = s[:] //切片在切片就能看到后来添加的值了
fmt.Printf("s的地址:%p |s的长度:%d |s的容量:%d\n", s, len(s), cap(s)) //s的地址:0xc00000c2c0 |s的长度:5 |s的容量:8
fmt.Printf("切片s的值:%v\n", s) //切片s的值:[0 0 0 0 0]
s = s[:8] //切片在切片就能看到后来添加的值了
fmt.Printf("s的地址:%p |s的长度:%d |s的容量:%d\n", s, len(s), cap(s)) //s的地址:0xc00000c2c0 |s的长度:5 |s的容量:8
fmt.Printf("切片s的值:%v\n", s) //切片s的值:[0 0 0 0 0]
}
输出结果:
结论:切片在传参过程中,形参已经做出来内容改变,实参也会做出改变。条件是形参在长度,容量定义范围内。为什么s=s[:]不能显示出来{1,0,0,0,0,1,2}呢?我认为是s在main中默认使用声明中的长度5,而不是change函数改变过的7导致。
3、假如在change函数中对形参进行扩展容量追加。结果怎么样?
测试:
package main
import "fmt"
func change(a []int) {
a[0] = 1
a = append(a, 1, 2, 3, 4)
fmt.Printf("a的地址:%p |a的长度:%d |a的容量:%d\n", a, len(a), cap(a)) //a的地址:0xc00000c2c0 |a的长度:7 |a的容量:8
fmt.Printf("a的值:%v\n", a) //a的值:[1 0 0 0 0 1 2 3 4]
}
func main() {
s := make([]int, 5, 8)
fmt.Printf("s的地址:%p |s的长度:%d |s的容量:%d\n", s, len(s), cap(s)) //s的地址:0xc00000c2c0 |s的长度:5 |s的容量:8
fmt.Printf("切片s的值:%v\n", s) //切片s的值:[0 0 0 0 0]
change(s)
s = s[:] //切片在切片就能看到后来添加的值了
fmt.Printf("s的地址:%p |s的长度:%d |s的容量:%d\n", s, len(s), cap(s)) //s的地址:0xc00000c2c0 |s的长度:5 |s的容量:8
fmt.Printf("切片s的值:%v\n", s) //切片s的值:[0 0 0 0 0]
s = s[:8] //切片在切片就能看到后来添加的值了
fmt.Printf("s的地址:%p |s的长度:%d |s的容量:%d\n", s, len(s), cap(s)) //s的地址:0xc00000c2c0 |s的长度:5 |s的容量:8
fmt.Printf("切片s的值:%v\n", s)
}
输出结果
结论:一旦实参的切片通过形参重新改变原来实参的切片长度与容量后,形参的变化不会导致实参的变化了。但是实参的切片与形参的切片首个单元地址值还是保持不变。