Refs
原文:Go Slices: usage and internals
The Go Programming Language Specification
Array
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就能够及时回收无用的数据。
网友评论