len
):表示切片当前可见的元素个数。cap
):表示从切片起始位置到底层数组末尾的最大可用元素数量。Go 的切片在内存中的结构可以用以下类型表示:
type SliceHeader struct {
Data uintptr // 底层数组的起始地址
Len int // 切片的长度
Cap int // 切片的容量
}
myNum := []int{10,20,30,40,50}
newNum := myNum[1:3]
newNum切片的内存结构:
(1)创建切片
字面量创建:
s := []int{1, 2, 3, 4} // 创建一个长度为 4 的切片
通过 make
函数创建:
s := make([]int, length, capacity)
通过数组创建:
arr := [5]int{1, 2, 3, 4, 5}
s := arr[1:4] // 创建一个子切片 [2, 3, 4]
(2)添加切片元素
使用append函数可以向切片追加一个或多个元素。如果追加的元素超出了当前切片的容量,append会分配一个新的底层数组,并将原切片的内容以及新元素复制到新数组中。
data := [...]int{0, 1, 2, 3, 4, 10: 0}
s := data[:2:3]//slice内容为data从0到1,容量cap为3
s = append(s, 100, 200) // 一次 append 两个值,超出 s.cap 限制。
fmt.Println(s, data) // 重新分配底层数组,与原数组无关。
fmt.Println(&s[0], &data[0]) // 比对底层数组起始指针。
输出结果:
[0 1 100 200] [0 1 2 3 4 0 0 0 0 0 0]
0xc4200160f0 0xc420070060
从输出结果可以看出,append 后的 s 重新分配了底层数组,并复制数据。 通常以 2 倍容量重新分配底层数组。
(3)切片拷贝
s1 := []int{1,2,3}
s2 := make([]int,3)
copy(s2,s1) //现在s2是{1,2,3}的拷贝
(4)字符串和切片
string本身是不可变的,因此要修改string中字符。需要如下操作:
str := "Hello world"
s := []byte(str) //中文字符需要用[]rune(str)
s[6] = 'G'
s = s[:8]
str = string(s)
fmt.Println(str)
输出结果:
Hello Go
数组 or 切片 转字符串:
strings.Replace(strings.Trim(fmt.Sprint(array_or_slice), "[]"), " ", ",", -1)