1、切片创建
切片(slice)解决了数组长度不能扩展,以及基本类型数组传递时产生副本的问题。
常用创建方式:
1 2 3 4
| var s1 []int s2 := []byte {'a','b','c'} fmt.Println(s1) fmt.Print(s2)
|
使用make函数创建:
1 2 3
| slice1 := make([]int,5) slice2 := make([]int,5,7) slice3 := []int{1,2,3,4,5}
|
从数组创建:slice 可以从一个数组再次声明。slice 通过 array[i:j]
来获取,其中 i 是数组的开始位置,j 是结束位置,但不包含 array[j]
,它的长度是 j-i
:
1 2 3 4 5 6 7 8 9 10
| var arr = [10]byte {'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
var a, b []byte
a = arr[2:5]
b = arr[3:5]
|
注意:声明数组时,方括号内写明了数组的长度或使用…自动计算长度,而声明 slice 时,方括号内没有任何字符。
从切片创建:
1 2
| oldSlice := []int{1,2,3} newSlice := oldSlice[:6]
|
注意:如果选择的旧切片长度超出了旧切片的 cap()
值(切片存储长度),则不合法。
2、切片常见操作
2.1、切片常见内置函数
切片常用内置函数:
1 2 3 4
| len() 返回切片长度 cap() 返回切片底层数组容量 append() 对切片追加元素 func copy(dst, src []Type) int 将src中数据拷贝到dst中,返回拷贝的元素个数
|
切片空间与元素个数:
1 2 3 4
| slice1 := make([]int, 5, 10) fmt.Println(len(slice1)) fmt.Println(cap(slice1)) fmt.Println(slice1)
|
切片操作
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| slice1 = append(slice1,1,2) fmt.Println(slice1)
sliceTemp := make([]int,3) slice1 = append(slice1,sliceTemp...) fmt.Println(slice1)
s1 := []int{1,3,6,9} s2 := make([]int, 10) num := copy(s2, s1)
fmt.Println(s1) fmt.Println(s2) fmt.Println(num)
s1 := []int{1,3,6,9} index := 2 s1 = append(s1[:index], s1[index+1:]...) fmt.Println(s1)
s1 := []int{1,2,3,4,5} s2 := []int{6,7,8} copy(s1,s2) copy(s2,s1)
|
注意:没有…会编译错误,默认第二个参数后是元素值,传入切片需要展开。如果追加的长度超过当前已分配的存储空间,切片会自动分配更大的内存。
2.2、切片的一些简便操作
- slice 的默认开始位置是0,
ar[:n]
等价于 ar[0:n]
- slice 的第二个序列默认是数组的长度,
ar[n:]
等价于 ar[n:len(ar)]
- 如果从一个数组里面直接获取 slice,可以这样
ar[:]
,因为默认第一个序列是0,第二个是数组的长度,即等价于 ar[0:len(ar)]
- 切片的遍历可以使用 for 循环,也可以使用 range 函数
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35
| var array = [10]byte{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j'}
var aSlice, bSlice []byte
aSlice = array[:3] aSlice = array[5:] aSlice = array[:]
aSlice = array[3:7] bSlice = aSlice[1:3] bSlice = aSlice[:3] bSlice = aSlice[0:5] bSlice = aSlice[:] ```
## 2.3、切片的截取
* `s[n]`:切片s中索引为位置为n的项 * `s[:]`:从切片s的索引位置0到`len(s)-1`所获得的切片 * `s[low:]`:从切片s的索引位置low到`len(s)-1`所获得的切片 * `s[:high]`:从切片s的索引位置0到high所获得的切片 * `s[low:high]`:从切片s的索引位置low到high所获得的切片 * `s[low:high:max]`:从low到high的切片,且容量`cap=max-low`
## 2.4、字符串转切片
```go str := "hello,世界" a := []byte(str) b := []rune(str)
|
3、切片存储结构
与数组相比,切片多了一个存储能力值的概念,即元素个数与分配空间可以是两个不同的值,其结构如下所示:
1 2 3 4 5
| type slice struct { arrary = unsafe.Pointer len int cap int }
|
所以切片通过内部的指针和相关属性引用数组片段,实现了变长方案,Slice 并不是真正意义上的动态数组。
合理设置存储能力,可以大幅提升性能,比如知道最多元素个数为50,那么提前设置为50,而不是先设为30,可以明显减少重新分配内存的操作。
4、切片作为函数参数
1 2 3 4 5 6 7 8 9 10 11 12 13
| func test(s []int) { fmt.Printf("test---%p\n", s) s = append(s, 1, 2, 3, 4, 5) fmt.Printf("test---%p\n", s) fmt.Println("test---", s) }
func main() { s1 := make([]int, 3) test(s1) fmt.Printf("main---%p\n", s1) fmt.Println("main---", s1) }
|