【go源码分析】go源码之slice源码分析

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/zhonglinzhang/article/details/83893048

Go 语言切片是对数组的抽象。

Go 数组的长度不可改变,与数组相比切片的长度是不固定的,可以追加元素,在追加时可能使切片的容量增大。

len() 和 cap() 函数

    切片是可索引的,并且可以由 len() 方法获取长度。

    切片提供了计算容量的方法 cap() 可以测量切片最长可以达到多少。

空(nil)切片

    一个切片在未初始化之前默认为 nil,长度为 0

结构体

  slice结构体

    一个指向array地址的指针,slice的长度len和容量cap

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

1. makeslice函数

    调用mallocgc分配连续的地址

func makeslice(et *_type, len, cap int) slice {
	// NOTE: The len > maxElements check here is not strictly necessary,
	// but it produces a 'len out of range' error instead of a 'cap out of range' error
	// when someone does make([]T, bignumber). 'cap out of range' is true too,
	// but since the cap is only being supplied implicitly, saying len is clearer.
	// See issue 4085.
	maxElements := maxSliceCap(et.size)
	if len < 0 || uintptr(len) > maxElements {
		panicmakeslicelen()
	}

	if cap < len || uintptr(cap) > maxElements {
		panicmakeslicecap()
	}

	p := mallocgc(et.size*uintptr(cap), et, true)
	return slice{p, len, cap}
}

2. growslice函数

    slice扩大容量函数,这块可以看出来怎么增长容量

  •     < 1024,按照两倍增长
  •     否则按照1.25倍增长
  •     扩容会涉及数据拷贝,产生性能开销
	newcap := old.cap
	doublecap := newcap + newcap
	if cap > doublecap {
		newcap = cap
	} else {
		if old.len < 1024 {
			newcap = doublecap
		} else {
			// Check 0 < newcap to detect overflow
			// and prevent an infinite loop.
			for 0 < newcap && newcap < cap {
				newcap += newcap / 4
			}
			// Set newcap to the requested cap when
			// the newcap calculation overflowed.
			if newcap <= 0 {
				newcap = cap
			}
		}
	}

猜你喜欢

转载自blog.csdn.net/zhonglinzhang/article/details/83893048