GO中的切片

Refs
原文:Go Slices: usage and internals
The Go Programming Language Specification
Effect GO
Array
【GO中的切片】Go中的数组对象代表着整个数组,而是指向首元素的指针。当传递数组对象时,传递的是整个数组的值。

b := [...]string{"a", "b", "c"}

Slices
Slices的声明与Array类似,但是省略了长度信息。
l := []string{"a", "b", "c"}

或者使用内置的make方法
l = make([]string, len, cap)

Array和Slices的切片操作会产生Slices对象
Slices实现原理
  • make([]byte, 5)会产生下图中的结构:


  • s = s[2:4]后cap会剔除前方的长度(5 - 2 = 3):


  • 切片操作没有拷贝Slice的数据,而是创建了左侧的结构并把指针指向起始位置。因此,操作切片结果是,会影响到原有的数据;
  • s = s[:cap(s)]来使用全部空间;
COPY 增加slice容量只能通过分配新的slice空间、拷贝数据来实现。
s := [3]byte{'a', 'b', 'c'} t := make([]byte, len(s), (cap(s) + 1) * 2) copy(t, s) s = t

APPEND
func AppendByte(slice []byte, data ... byte) []byte { m := len(slice) n := m + len(data) if n > cap(slice) { newSlice := make([]byte, (n + 1) * 2) copy(newSlice, slice) slice = newSlice } slice = slice[0:n]// len == cap copy(slice[m:n], data) return slice }

  • 添加元素
p := []byte{2, 3, 5} p = p.append(p, 1, 2)

  • 添加slice
a := []string{"a", "b", "c"} b := []string{"e", "f", "g"} b = append(a, b...)

func Filter(s []int, fn func(int) bool) [] int { var p []int// nil for _, v := range s { if fn(v) { p = append(p, v) } } return p }

疑思 当只需要大量数据的一小部分时,如果对大量数据做切片操作,那么这些数据都会保留在内存中。例如,读取文件中数据并返回特定片断的程序。
这种情况下,建议构造目标数据的切片进行返回,这样GC就能够及时回收无用的数据。

    推荐阅读