美文网首页程序员
golang slice学习

golang slice学习

作者: Lucas_Ye | 来源:发表于2017-01-03 19:51 被阅读89次

1. slice的结构

type slice struct {
      index  *interface  //指向首元素的指针
      len    int         //长度
      cap    int         //容量
}
slice是类型

slice类型声明后类似于:
var arr slice 而非 var arr *slice
append时,如果超过cap容量,会重新分配空间.
新空间的指针会被保存在index中,slice本身的指针不变.
举个栗子🌰:

func F() {
   intArr := make([]int, 1)
   fmt.Println(&intArr[0], len(intArr), cap(intArr))
   defer f(intArr)
   intArr = append(intArr, 1)
   fmt.Println(&intArr[0], len(intArr), cap(intArr))
   return
}

func f(intArr []int) {
   fmt.Println(&intArr[0], len(intArr), cap(intArr))
}

//结果
0xc42000d2d0 1 1
0xc42000d300 2 2
0xc42000d2d0 1 1
  • 在defer中,保存了一个副本,拷贝了intArr的值,
    在后面append中,因为容量(cap)不够,给intArr的index重新分配了空间,
    因为defer中保存的是intArr的值,所以defer打印出来的是原来的slice值
func F1() {
   intArr := make([]int, 1)
   fmt.Println(&intArr[0], len(intArr), cap(intArr))
   defer f1(&intArr)
   intArr = append(intArr, 1)
   fmt.Println(&intArr[0], len(intArr), cap(intArr))
   return
}

func f1(ia *[]int) {
   intArr := *ia
   fmt.Println(&intArr[0], len(intArr), cap(intArr))
}

//结果
0xc42000d2d0 1 1
0xc42000d300 2 2
0xc42000d300 2 2
  • 在defer中,保存了一个副本,拷贝了intArr的指针,
    在后面append中,因为容量(cap)不够,给intArr的index重新分配了空间,
    因为defer中保存的是intArr的指针,所以打印出来的是新的的slice值

2. slice的扩容

func F() {
     intArr := make([]int, 0, 0)

     intArr = append(intArr, 1)
     fmt.Println(&intArr[0], len(intArr), cap(intArr))

     intArr = append(intArr, 2)
     fmt.Println(&intArr[0], len(intArr), cap(intArr))

     intArr = append(intArr, 3)
     fmt.Println(&intArr[0], len(intArr), cap(intArr))

     intArr = append(intArr, 4)
     fmt.Println(&intArr[0], len(intArr), cap(intArr))
     return
}

//结果
0xc42000d2d0 1 1
0xc42000d300 2 2
0xc4200cc660 3 4
0xc4200cc660 4 4

在对slice进行append等操作时,可能会造成slice的自动扩容。其扩容时的大小增长规则是:

  • 如果新的大小是当前大小2倍以上,则大小增长为新大小
  • 否则循环以下操作:如果当前大小小于1024,按每次2倍增长,否则每次按当前大小1/4增长。直到增长的大小超过或等于新大小。

相关文章

网友评论

    本文标题:golang slice学习

    本文链接:https://www.haomeiwen.com/subject/yzynvttx.html