golang 基础(15)slice 的操作
2019-03-18 本文已影响28人
zidea
square-gopher.png
slice 的操作
Slice-Bread-Step-27.jpgslice 添加元素
s := arr[2:6]
fmt.Println(cap(s)) //6
fmt.Println(len(s)) //4
s1 := s[3:5]
fmt.Println("s = ",s)
fmt.Println("s1 = ",s1)
s2 := append(s1,10)
s3 := append(s2,11)
s5 := append(s3,12)
s2, s3, s5 = [5 6 10] [5 6 10 11] [5 6 10 11 12]
s6 := append(s5,15)
fmt.Println("s2, s3, s5 = ", s2, s3, s5,s6)
fmt.Println("arr = ",arr)
s2, s3, s5 = [5 6 10] [5 6 10 11] [5 6 10 11 12] [5 6 10 11 12 15]
arr = [0 1 2 3 4 5 6 10]
从输出接口来看 arr 还是保持原有长度,从 s3 开始以后 slice 不再是 arr 的片段,而是系统新建一个 arr
向 slice 添加元素时
- 添加元素时如果超越 cap, 系统会重新分配更大的底层数组,会将整个原有数组复制过去。如果原来数组不在被使用,就会被 GC 掉。
- 由于值传递的关系,必须接收 append 的返回值
[slice_append.JPG]
a := make([]int, 7,15)
b :=a[3:7]
z := len(b)
fmt.Println(z)
z = cap(b)
fmt.Println(z)
func foo() []int{
var a [5]int
return a[:]
}
创建一个 slice 然后通过 append 不断向 slice 进行添加值,看一看整个 slice 随着值增加,他的 len 和 cap 是如何变化的。
func printSlice(s []int){
fmt.Printf("len=%d, cap%d\n", len(s), cap(s))
}
func main(){
var s []int
for i := 0; i < 100; i++{
printSlice(s)
s = append(s, 2 * i + 1)
}
fmt.Println(s)
}
输出
len=0, cap0
len=1, cap1
len=2, cap2
len=3, cap4
len=4, cap4
len=5, cap8
len=6, cap8
len=7, cap8
len=8, cap8
len=9, cap16
len=10, cap16
len=11, cap16
len=12, cap16
len=13, cap16
len=14, cap16
len=15, cap16
len=16, cap16
len=17, cap32
len=18, cap32
len=19, cap32
len=20, cap32
len=21, cap32
len=22, cap32
len=23, cap32
len=24, cap32
len=25, cap32
len=26, cap32
len=27, cap32
len=28, cap32
len=29, cap32
len=30, cap32
len=31, cap32
len=32, cap32
len=33, cap64
len=34, cap64
len=35, cap64
len=36, cap64
len=37, cap64
len=38, cap64
len=39, cap64
len=40, cap64
len=41, cap64
len=42, cap64
len=43, cap64
len=44, cap64
len=45, cap64
len=46, cap64
len=47, cap64
len=48, cap64
len=49, cap64
len=50, cap64
len=51, cap64
len=52, cap64
len=53, cap64
len=54, cap64
len=55, cap64
len=56, cap64
len=57, cap64
len=58, cap64
len=59, cap64
len=60, cap64
len=61, cap64
len=62, cap64
len=63, cap64
len=64, cap64
len=65, cap128
len=66, cap128
len=67, cap128
len=68, cap128
len=69, cap128
len=70, cap128
len=71, cap128
len=72, cap128
len=73, cap128
len=74, cap128
len=75, cap128
len=76, cap128
len=77, cap128
len=78, cap128
len=79, cap128
len=80, cap128
len=81, cap128
len=82, cap128
len=83, cap128
len=84, cap128
len=85, cap128
len=86, cap128
len=87, cap128
len=88, cap128
len=89, cap128
len=90, cap128
len=91, cap128
len=92, cap128
len=93, cap128
len=94, cap128
len=95, cap128
len=96, cap128
len=97, cap128
len=98, cap128
len=99, cap128
[1 3 5 7 9 11 13 15 17 19 21 23 25 27 29 31 33 35 37 39 41 43 45 47 49 51 53 55 57 59 61 63 65 67 69 71 73 75 77 79 81 83 85 87 89 91 93 95 97 99 101 103 105 107 109 111 113 115 117 119 121 123 125 127 129 131 133 135 137 139 141 143 145 147 149 151 153 155 157 159 161 163 165 167 169 171 173 175 177 179 181 183 185 187 189 191 193 195 197 199]
func printSlice(s []int){
fmt.Printf("%v, len=%d, cap%d\n", s, len(s), cap(s))
}
然后使用其他创建方式在创建 slice
s1 := []int{2, 4, 6, 8}
printSlice(s1)
s2 := make([]int,16) //指定长度为16
printSlice(s2)
s3 := make([]int, 10, 32) //指定长度为 10 可扩展 32
printSlice(s3)
输出
[2 4 6 8], len=4, cap4
[0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap16
[0 0 0 0 0 0 0 0 0 0], len=10, cap32
复制 slice
copy(s2,s1)
printSlice(s2)
输出
[2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0], len=16, cap16
删除一个元素
// s2[:3] + s2[4:]
fmt.Println("before deleting s2 = ", s2)
s2 = append(s2[:3],s2[4:]...)
fmt.Println("after deleting s2 = ", s2)
其实 append 函数,看一看 append(slice []Type, elems ...Type) [] Type 源码,append 第二参数是一个可变的参数,那么可以将 slice... 先将 slice 解构为一个一个的元素,然后作为参数传进去。
输出
before deleting s2 = [2 4 6 8 0 0 0 0 0 0 0 0 0 0 0 0]
after deleting s2 = [2 4 6 0 0 0 0 0 0 0 0 0 0 0 0]
pop 和 tail 方法
在其他语言中基本提供了集合这样操作,不过 go 应该最求极简主义吧,如果能有基本方法实现的方法,作者就不愿追加这些方法。
fmt.Println("Popping from front")
front := s2[0]
s2 = s2[1:]
fmt.Println("Popping from back")
tail := s2[len(s2) - 1]
s2 = s2[:len(s2) - 1]
images.png