golang 基礎(15)slice 的操作

square-gopher.png
slice 的操作

Slice-Bread-Step-27.jpg
slice 新增元素
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