Go Slice 使用中的小陷阱

go中的切片有两个特性:

  • 底层的数据结构是数组
type slice struct {
  array unsafe.Pointer
  len   int
  cap   int
}

包括从切片和数组派生出来的切片都是公用一个底层数组的

  • 当往切片append的元素超过容量时,即len(s) < cap(s)时,底层的数组会重新分配一个容量更大的数组
  • make构造出来的切片,已经预先填充了len个零值元素了。

总而言之,对切片的更改都会影响到底层的数组结构,因此需要慎重。
动手做个实验:

package main

import (
	"fmt"
)

func double(s []int, count int) {
  fmt.Println("函数调用内切片的长度为", len(s), " 容量为", cap(s))
  for i:=0; i < count; i++ {
    s = append(s, 100) 
  }

  for i, v := range s {
    s[i] = v * 2
  }
}

func main() {
  s := make([]int, 5, 10)
  // 下面的赋值会改变s的底层数组,导致上面指定的容量10失效
  // s = []int{
  //   1, 2, 3, 4, 5,
  // }
  for i:=0; i < 5; i++ {
    s[i] = i + 1
  }

  fmt.Println("主函数内切片的长度为", len(s), " 容量为", cap(s))
  fmt.Println(s)
  double(s, 1)
  fmt.Println(s)
  // 添加超过切片容量的元素后,double函数内切片底层的数组重新分配了,和主函数外的切片的底层数组不是同一个了,因此对其修改不会影响到主函数切片的数值
  double(s, 10)
  fmt.Println(s)
}
原文地址:https://www.cnblogs.com/linyihai/p/10625011.html