golang中的切片
slice
注意,切片代表的窗口是無法向左擴展的
順便提一下把切片的窗口向右擴展到最大的方法。對于s4來說,切片表達式s4[0:cap(s4)]就可以做到
一個切片的容量可以被看作是透過這個窗口最多可以看到的底層數組中元素的個數
切片并不是數組或數組指針,它通過內部指針和相關屬性引用數組片段,以實現變長方案
slice并不是真正意義上的動態數組,而是一個引用類型.slice總是指向一個底層array, slice的聲明也可以像array一樣,只是不需要長度
可以把切片看做是對數組的一層簡單的封裝,因為在每個切片的底層數據結構中,一定會包含一個數組。數組可以被叫做切片的底層數組,而切片也可以被看作是對數組的某個連續片段的引用。
在這種情況下,切片的容量實際上代表了它的底層數組的長度
[low:high:max] low起點 high終點(不包括此下標) cap = max-low, 容量 func main() {a := []int{1, 2, 3, 4, 5}s := a[0:3:5]fmt.Println("s = ", s)//長度fmt.Println("len(s) = ", len(s))//容量fmt.Println("cap(s) = ", cap(s)) }輸出
s = [1 2 3] len(s) = 3 cap(s) = 5多維的切片
[][]int{{10,20},{30}}數組和切片的區別
func main() {a := [5]int{}fmt.Printf("len = %d, cap = %d\n", len(a), cap(a))s := []int{}fmt.Println(len(s), cap(s))s = append(s, 11)fmt.Printf("append: len = %d, cap = %d\n", len(s), cap(s)) }輸出
len = 5, cap = 5 0 0 append: len = 1, cap = 1切片的創建
func main() {//自動推導類型,同時初始化s1 := []int{1, 2, 3, 4}fmt.Println("s1 = ", s1)//借助make函數,格式make(切片類型,長度,容量)s2 := make([]int, 5, 10)fmt.Println(len(s2), cap(s2))//沒有指定容量,容量和長度一樣s3 := make([]int, 5)fmt.Println(len(s3), cap(s3)) }切片的截取
切片和底層數組的關系
會改變底層數組
func main() {a := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}//新切片s1 := a[2:5]s1[1] = 666fmt.Println("s1 = ", s1)fmt.Println("a = ", a)//另外切片s2 := s1[2:7]s2[2] = 777fmt.Println("s2 = ", s2)fmt.Println("a = ", a) }輸出
s1 = [2 666 4] a = [0 1 2 666 4 5 6 7 8 9] s2 = [4 5 777 7 8] a = [0 1 2 666 4 5 777 7 8 9]易錯
一個切片是以另一個切片為基礎切,容量一樣那么都是指向同一個東西
func main() {data := []string{"red", "1", "black", "1", "pink", "red"}out := data[:1]for _, word := range data {fmt.Println("-----------")i:=0//比較取出的word是否在out中存在for ; i<len(out); i++ {if word == out[i] {fmt.Println(len(out))break}}if i== len(out) {out = append(out, word)fmt.Println(word)}}fmt.Println(data)fmt.Println(out) }append函數
會智能的底層數組的容量增長,一旦超過原底層數組容量,通常以2倍容量重新分配底層數組,并復制原來的數據
func main() {data := []string{"red", "1", "black", "1", "pink"}fmt.Printf("%v\n", data)out := data[:0]fmt.Printf("%v\n", out)for _, str := range data{if str != "1" {out = append(out, str)}}fmt.Printf("%v\n", data) //感覺奇怪fmt.Printf("%v\n", out)//[red 1 black 1 pink]//[]//[red black pink 1 pink]//[red black pink] }如果不想里面有空的元素,就make的len為0,cap為0
slice := make([]string, 0) slice = append(slice, "111") slice = append(slice, "222") slice = append(slice, "33") for _, data := range slice {fmt.Println("data----", data) }slice:=append([]int{1,2,3},[]int{4,5,6}...)
fmt.Println(slice)//[1 2 3 4 5 6]
- 還有種特殊用法,將字符串當作[]byte類型作為第二個參數傳入
copy
copy會把一些位置替換
func main() {srcSlice := []int{1, 2}dstSlice := []int{6, 6, 6, 6, 6}copy(dstSlice, srcSlice)fmt.Println("dst = ", dstSlice) }輸出
dst = [1 2 6 6 6]作為函數參數
是引用傳遞,里面改了,外面也一樣會改
complexArray1 := [3][]string{[]string{"d", "e", "f"},[]string{"g", "h", "i"},[]string{"j", "k", "l"}, }變量complexArray1是[3][]string類型的,也就是說,雖然它是一個數組,但是其中的每個元素又都是一個切片。這樣一個值被傳入函數的話,函數中對該參數值的修改會影響到complexArray1本身嗎?
分2種情況,若是修改數組中的切片的某個元素,會影響原數組。若是修改數組的某個元素即a[1]=[]string{"x"}就不會影響原數組。謹記Go中都是淺拷貝,值類型和引用類型的區別
nil
目前已知只有var s []int這1種方法才是nil slice。其他情況都不是,因為只有no underlying array才是nil slice
下面幾種方法都不是nil slice
s := []int{}不是nil
刪除所有元素也不算是nil,如
sli = sli[:cap(sli)] sli = sli[len(sli):]用make([]int, 0, 0)也不是nil
嵌套
slice可以嵌套包含slice,并且可以嵌套多層。也可以叫做多維slice。另外,array也支持多維array(這里就不提了)
嵌套一層
board1 := [][]string{[]string{"_", "_", "_"},[]string{"_", "_", "_"},[]string{"_", "_", "_"}, }支持簡寫
比如上面這個例子可以改為
b := [][]string{{"_", "_", "_"},{"_", "_", "_"},{"_", "_", "_"}, }嵌套兩層
board2 := [][][]string{[][]string{[]string{"_", "_", "_"},[]string{"_", "_", "_"},[]string{"_", "_", "_"},},[][]string{[]string{"_", "_", "_"},[]string{"_", "_", "_"},[]string{"_", "_", "_"},},[][]string{[]string{"_", "_", "_"},[]string{"_", "_", "_"},[]string{"_", "_", "_"},}, }賦值
board1[0][0] = "X" board2[0][0][0] = "Y"通過嵌套實現了高級數據結構,比如python中列表嵌套字典嵌套列表等等
總結
以上是生活随笔為你收集整理的golang中的切片的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: golang中的指针
- 下一篇: golang中的os包