Array
数组是值,赋值、传参时会复制
数组不需要显式的初始化操作
var a [4]int
a[2] == 0
- 在内存中分配一块连续的内存,在内存中布局:
Slice
make
- 定义如下:
func make([]T, len, cap) []T
- cap 是切片的初始容量,cap 是可选参数,如果省略,默认为 len。
s := make([]byte, 5)
len(s) == 5
cap(s) == 5
- cap 不可以小于 len,否则会有编译错误
package main
import (
"fmt"
)
func main() {
defer func() {
if err := recover(); err != nil {
fmt.Printf("Recover from error: %v", err)
}
}()
s := make([]int, 5, 4)
fmt.Printf("len = %d, cap = %d", len(s), cap(s))
}
// prog.go:13:11: len larger than cap in make([]int)
内部结构
上图中,ptr
是指向array的pointer,len
是指切片的长度, cap
指的是切片的容量。
这里为什么 cap 变成 3 了呢?
s := x[2:4]
len(s) == 2
cap(s) == 3
- Growing
t := make([]byte, len(s), (cap(s)+1)*2) // +1 in case cap(s) == 0
for i := range s {
t[i] = s[i]
}
s = t
- 通过 copy 实现一个通用的追加操作
func AppendByte(slice []byte, data ...byte) []byte {
m := len(slice)
n := m + len(data)
if n > cap(slice) { // if necessary, reallocate
// allocate double what's needed, for future growth.
newSlice := make([]byte, (n+1)*2)
copy(newSlice, slice)
slice = newSlice
}
slice = slice[0:n]
copy(slice[m:n], data)
return slice
}
- 与函数配合使用
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
}
- append 方法
package main
import (
"fmt"
)
func main() {
s := []int{}
fmt.Println(len(s), cap(s))
for i := 0; i < 8; i++ {
s = append(s, i)
fmt.Println(len(s), cap(s))
}
}
// 0 0
// 1 2
// 2 2
// 3 4
// 4 4
// 5 8
// 6 8
// 7 8
// 8 8
nil
package main
import (
"fmt"
)
func main() {
var s []int = nil
fmt.Println(len(s))
s = append(s, 1)
fmt.Println(len(s))
}
// 0
// 1