go slice append 分析


先看一段代码:

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	p1 := s[:3]
	p2 := s[4:]
	p3 := append(p1, p2...)
	fmt.Printf("p1 = %v \n", p1)
	fmt.Printf("p2 = %v \n", p2)
	fmt.Printf("p3 = %v \n", p3)
}

运行结果:

p1 = [1 2 3] 
p2 = [6 7 8 9 9] 
p3 = [1 2 3 5 6 7 8 9]

结果是对的。但是p2的值就说明一些问题
期望值应该是:

p2 = [5 6 7 8 9]

下面看一下实际运行的流程:

func main() {
	s := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
	p1 := s[:3]
	p2 := s[4:]
	fmt.Printf("s = %p s = %v \n", s, s)
	fmt.Printf("p1 = %p v1 = %v len = %v \n", p1, p1, len(p1))
	fmt.Printf("p2 = %p v2 = %v len = %v \n", p2, p2, len(p2))
	p3 := append(p1, p2...)
	fmt.Printf("s = %p s = %v \n", s, s)
	fmt.Printf("p1 = %p v1 = %v \n", p1, p1)
	fmt.Printf("p2 = %p v2 = %v \n", p2, p2)
	fmt.Printf("p3 = %p v3 = %v \n", p3, p3)
}

运行结果:

PS D:\test\test> go run main.go
s = 0xc00000c320 s = [1 2 3 4 5 6 7 8 9] 
p1 = 0xc00000c320 v1 = [1 2 3] len = 3 
p2 = 0xc00000c340 v2 = [5 6 7 8 9] len = 5
s = 0xc00000c320 s = [1 2 3 5 6 7 8 9 9]
p1 = 0xc00000c320 v1 = [1 2 3]
p2 = 0xc00000c340 v2 = [6 7 8 9 9]
p3 = 0xc00000c320 v3 = [1 2 3 5 6 7 8 9]

解释:
*p3 == *s
append操作的是0xc00000c320指针,也就是s变量,
所以,在执行完append后,s的值已经改变,p1,p2的结果是截取切片s的,所以p1,p2
也会跟着变化。
*p1 != *p2
说明截取切片存储的值应该是

p1 = *s[:3]
p2 = *s[4:]