Notes: Go Slice

YuHaibo
YuHaibo
Mar 25, 2018 · 5 min read

Go 的 slice 是在数组之上的抽象数据类型, 与数组有所不同.

type slice struct {
array unsafe.Pointer
len int
cap int
}
https://github.com/golang/go/blob/master/src/runtime/slice.go#L11

一个 slice 包含了指向数组的指针,片段的长度和容量, 长度不超过容量, 可以进行扩容.

基本用法

创建:
letters := []string{"a", "b", "c", "d"}
var s []byte
s = make([]byte, 5, 5)
s := make([]byte, 5)获取长度和容量信息, 使用内置函数:
len(s) == 5
cap(s) == 5
从已有切片或者数组创建:
b := []byte{'g', 'o', 'l', 'a', 'n', 'g'}
// b[1:4] == []byte{'o', 'l', 'a'}
// b[1:4] 表示索引的第 1 个到 第 4-1 个, 即索引为 1,2,3 的元素
// b[:2] == []byte{'g', 'o'} 开始索引默认 0
// b[2:] == []byte{'l', 'a', 'n', 'g'} 结束索引默认 len
// b[:] == b
零值:
slice 的零值是 nil
一个 nil 的 slice 的长度和容量是 0.
复制:
func copy(dst, src []T) int
追加:
func append(s []T, x ...T) []T
a := make([]int, 1)
// a == []int{0}
a = append(a, 1, 2, 3)
// a == []int{0, 1, 2, 3}
追加切片需要使用...语法展开:
a := []string{"John", "Paul"}
b := []string{"George", "Ringo", "Pete"}
a = append(a, b...) // equivalent to "append(a, b[0], b[1], b[2])"
// a == []string{"John", "Paul", "George", "Ringo", "Pete"}

扩容

容量不足时可以扩容, 容量小于1024时, 翻倍扩容; 超过1024时, 为1.25倍;

扩容之后, 指向的数组如果空间足够, 会使用原有数组; 否则会创建新数组.

package mainimport "fmt"func main() {
demoArray := [3]int{1, 2, 3}
demoSlice := demoArray[0:2]
newSlice := append(demoSlice, 9)
fmt.Printf("%v %p %d %d \n", demoSlice, &demoSlice, len(demoSlice), cap(demoSlice))
fmt.Printf("%v %p %d %d \n", newSlice, &newSlice, len(newSlice), cap(newSlice))
newSlice[1] = 200
fmt.Printf("%v %p %d %d \n", demoSlice, &demoSlice, len(demoSlice), cap(demoSlice))
fmt.Printf("%v %p %d %d \n", newSlice, &newSlice, len(newSlice), cap(newSlice))
fmt.Println(demoArray)
}
//同一个数组, newSlice 影响了 demoSlice
[1 2] 0xc42000a080 2 3
[1 2 9] 0xc42000a0a0 3 3
[1 200] 0xc42000a080 2 3
[1 200 9] 0xc42000a0a0 3 3
[1 200 9]
package mainimport "fmt"func main() {
demoSlice := []int{1, 2, 3}
newSlice := append(demoSlice, 9)
fmt.Printf("%v %p %d %d \n", demoSlice, &demoSlice, len(demoSlice), cap(demoSlice))
fmt.Printf("%v %p %d %d \n", newSlice, &newSlice, len(newSlice), cap(newSlice))
newSlice[1] = 200
fmt.Printf("%v %p %d %d \n", demoSlice, &demoSlice, len(demoSlice), cap(demoSlice))
fmt.Printf("%v %p %d %d \n", newSlice, &newSlice, len(newSlice), cap(newSlice))
}
//新数组, 不会互相影响
[1 2 3] 0xc42000a080 3 3
[1 2 3 9] 0xc42000a0a0 4 6
[1 2 3] 0xc42000a080 3 3
[1 200 3 9] 0xc42000a0a0 4 6
YuHaibo

Written by

YuHaibo

Code & Life. 🏠 https://yuhaibo.com/

Welcome to a place where words matter. On Medium, smart voices and original ideas take center stage - with no ads in sight. Watch
Follow all the topics you care about, and we’ll deliver the best stories for you to your homepage and inbox. Explore
Get unlimited access to the best stories on Medium — and support writers while you’re at it. Just $5/month. Upgrade