Golang 切片作为函数参数的“陷阱”
我们知道 Go 中的切片类型是引用类型,直觉来讲在作为函数参数时,如果函数内部修改了切片的值,函数外的也会被修改,但这有个前提:只能修改切片的内容,而不能修改切片它本身。
如果用切片重组或者 append 方法修改了切片的长度或容量,得到的切片就不是原来那个了,因此变化不会反映到函数外。例如:
 | func main() { 	a := [5]int{1, 2, 3, 4, 5} 	s := a[:] 	changeSlice(s) 	fmt.Println(s) }
  func changeSlice(s []int) {      	s = s[:2]     s = append(s, 98) }
 
 
 
  | 
 
而如果修改了切片的内容,例如其中元素的值,切片的长度跟容量都没有变,会导致函数外部的切片也一起改变
1 2 3 4 5 6 7 8 9 10 11 12 13
   | func main() { 	a := [5]int{1, 2, 3, 4, 5} 	s := a[:] 	changeSlice(s) 	fmt.Println(s) }
  func changeSlice(s []int) {      	s[0] = 4396 }
 
 
 
  | 
 
传递切片的指针
如果实在想修改切片,可以传递切片的指针,解引用后进行操作
1 2 3 4 5 6 7 8 9 10 11 12 13
   | func main() { 	a := [5]int{1, 2, 3, 4, 5} 	s := a[:] 	changeSlice(&s) 	fmt.Println(s) }
  func changeSlice(s *[]int) {     *s = (*s)[:2] 	*s = append(*s, 4396) }
 
 
 
  | 
 
复制切片
如果需要保证切片(或它的关联数组)一定不会被修改,可以将原始切片用内置函数 copy() 复制后操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
   | func main() { 	a := [5]int{1, 2, 3, 4, 5} 	s := a[:] 	changeSlice(s) 	fmt.Println(s) }
  func changeSlice(s []int) { 	sCopied := make([]int, len(s)) 	copy(sCopied, s) 	sCopied[0] = 4396 	sCopied = append(sCopied, 7777) }
 
 
 
  | 
 
参考