从源码理解Go:slice

2016-11-15 阅读: Go

slice的内部结构

一个slice本质上是一个数组的某个部分的引用。在go runtime/slice.go源码中定义了slice的结构:

type slice struct {
	array unsafe.Pointer
	len   int
	cap   int
}

可以看到在Go的内部,slice是一个包含3个字段的结构体:

  • array: 指向slice第一个元素的指针
  • len: slice的长度,长度是索引操作的上届, s[i] i<len(s)
  • cap: slice的容量,容量是分割操作的上届, s[i:j] j<=cap(s)

slice扩容

当对slice进行append的操作时,当容量不够时会引起slice的扩容:

func growslice(et *_type, old slice, cap int) slice {
	......
	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.len < 1024 {
			newcap = doublecap
		} else {
			for newcap < cap {
				newcap += newcap / 4
			}
		}
	}
	......
	return slice{p, old.len, newcap}
}

从以上源码可以看出在扩容时:

  • 如果容量需求大于原cap的两倍以上,则扩容后容量即为需求的容量
  • 否则: * 如果原来的len小于1024,则扩容后的cap为原cap的两倍。即按原cap 2倍增长扩容 * 如果原来的len大于等于1024,按1/4增长计算新的cap,直到满足容量需求。

slice编程技巧

参考

标题:从源码理解Go:slice
本文链接:https://blog.frognew.com/2016/11/go-slice-comprehension.html
转载请注明出处。

目录