亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb

首頁 > 編程 > Golang > 正文

Go基礎Slice教程詳解

2020-04-01 18:58:59
字體:
來源:轉載
供稿:網友

Go 語言切片(Slice)

Go 語言切片是對數組的抽象。

Go 數組的長度不可改變,在特定場景中這樣的集合就不太適用,Go中提供了一種靈活,功能強悍的內置類型切片("動態數組"),與數組相比切片的長度是不固定的,可以追加元素,在追加時可能使切片的容量增大。

聲明Slice

帶有 T 類型元素的切片由 []T 表示,其中T代表slice中元素的類型。切片在內部可由一個結構體類型表示,形式如下:

type slice struct {  Length  int Capacity  int ZerothElement *byte}

可見一個slice由三個部分構成:指針、長度和容量。指針指向第一個slice元素對應的底層數組元素的地址。長度對應slice中元素的數目;長度不能超過容量,容量一般是從slice的開始位置到底層數據的結尾位置。通過len和cap函數分別返回slice的長度和容量。

創建Slice

直接聲明創建 slice

[]<元素類型>{元素1, 元素2, …}

創建一個有 3 個整型元素的數組,并返回一個存儲在 c 中的切片引用。

c := []int{6, 7, 8}

make() 函數創建 slice

s1 := make([]int, 5) //長度和容量都是 5 s2 := make([]int, 3, 10) //長度是3,容量是10 fmt.Println(cap(s1),s2)

基于底層數組數組或切片創建

基于現有的切片或者數組創建,使用[i:j]這樣的操作符即可,她表示以i索引開始,到j索引結束,截取原數組或者切片,創建而成的新切片,新切片的值包含原切片的i索引,但是不包含j索引。注意i和j都不能超過原切片或者數組的索引

slice :=[]int{1,2,3,4,5} slice1 := slice[:] slice2 := slice[0:] slice3 := slice[:5] fmt.Println(slice1) fmt.Println(slice2) fmt.Println(slice3)

新的切片和原數組或原切片共用的是一個底層數組,所以當修改的時候,底層數組的值就會被改變,所以原切片的值也改變了。

slice := []int{1, 2, 3, 4, 5} newSlice := slice[1:3] newSlice[0] = 10 fmt.Println(slice) fmt.Println(newSlice)

切片與數組的區別

1.切片不是數組,但是切片底層指向數組

2.切片本身長度是不一定的因此不可以比較,數組是可以的。

3.切片是變長數組的替代方案,可以關聯到指向的底層數組的局部或者全部。

4.切片是引用傳遞(傳遞指針地址),而數組是值傳遞(拷貝值)

5.切片可以直接創建,引用其他切片或數組創建

6.如果多個切片指向相同的底層數組,其中一個值的修改會影響所有的切片

切片的修改

切片自己不擁有任何數據。它只是底層數組的一種表示。對切片所做的任何修改都會反映在底層數組中。

package mainimport ( "fmt")func main() { arr := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9} slice := arr[2:5] fmt.Println("array before", arr) for i := range slice {  slice[i]++ } fmt.Println("array after ", arr)}

在上述程序的第 9 行,我們根據數組索引 2,3,4 創建一個切片 dslice 。for 循環將這些索引中的值逐個遞增。當我們使用 for 循環打印數組時,我們可以看到對切片的更改反映在數組中。該程序的輸出是

array before [0 1 2 3 4 5 6 7 8 9]array after [0 1 3 4 5 5 6 7 8 9]

當多個切片共用相同的底層數組時,每個切片所做的更改將反映在數組中。

package mainimport ( "fmt")func main() { array := [4]int{10, 20 ,30, 40} slice1 := array[:] slice2 := array[:] fmt.Println("array before change:", array) slice1[0] = 60 fmt.Println("array after modification to slice slice1:", array) slice2[1] = 70 fmt.Println("array after modification to slice slice2:", array)}

在 9 行中, numa [:] 缺少開始和結束值。開始和結束的默認值分別為 0 和 len (numa) 。兩個切片 nums1 和 nums2 共享相同的數組。該程序的輸出是

array before change: [10 20 30 40]array after modification to slice slice1: [60 20 30 40]array after modification to slice slice2: [60 70 30 40]

從輸出中可以清楚地看出,當切片共享同一個數組時,每個所做的修改都會反映在數組中。

切片的長度和容量

切片的長度是切片中的元素數。 切片的容量是從創建切片索引開始的底層數組中元素數。

package mainimport ( "fmt")func main() { fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"} fruitslice := fruitarray[1:3] fmt.Printf("length of slice %d capacity %d", len(fruitslice), cap(fruitslice)) // length of is 2 and capacity is 6}

在上面的程序中, fruitslice 是從 fruitarray 的索引 1 和 2 創建的。 因此, fruitlice 的長度為 2 。

fruitarray 的長度是 7。 fruiteslice 是從 fruitarray 的索引 1 創建的。因此, fruitslice 的容量是從 fruitarray 索引為 1 開始,也就是說從 orange 開始,該值是 6 。因此, fruitslice 的容量為 6。該程序]輸出切片的 **長度為 2 容量為 6 **。

切片可以重置其容量。任何超出這一點將導致程序運行時拋出錯誤。

package mainimport ( "fmt")func main() { fruitarray := [...]string{"apple", "orange", "grape", "mango", "water melon", "pine apple", "chikoo"} fruitslice := fruitarray[1:3] fmt.Printf("length of slice %d capacity %d/n", len(fruitslice), cap(fruitslice)) // length of is 2 and capacity is 6 fruitslice = fruitslice[:cap(fruitslice)] // re-slicing furitslice till its capacity fmt.Println("After re-slicing length is",len(fruitslice), "and capacity is",cap(fruitslice))}

在上述程序的第 11 行中, fruitslice 的容量是重置的。以上程序輸出為,

length of slice 2 capacity 6 After re-slicing length is 6 and capacity is 6

追加切片元素

正如我們已經知道數組的長度是固定的,它的長度不能增加。 切片是動態的,使用 append 可以將新元素追加到切片上。append 函數的定義是

func append(s[]T,x ... T)[]T

append可以直接在切片尾部追加元素,也可以將一個切片追加到另一個切片尾部。

package mainimport ( "fmt")func main() { str := []string{"a", "b", "c"} fmt.Println("strs:", str, " length:", len(str), "capacity:", cap(str)) str = append(str, "d") fmt.Println("strs:", str, " length:", len(str), " capacity:", cap(str))}

在上述程序中, str 的容量最初是 3。在第 10 行,我們給 str 添加了一個新的元素,并把 append(str, "d") 返回的切片賦值給 str。現在 str 的容量翻了一番,變成了 6。

strs: [a b c] length: 3 capacity: 3strs: [a b c d] length: 4 capacity: 6

切片類型的零值為 nil 。一個 nil 切片的長度和容量為 0。可以使用 append 函數將值追加到 nil 切片。

package mainimport (  "fmt")func main() {  var strs []string //zero value of a slice is nil if strs == nil {  fmt.Println("slice is nil going to append")  strs = append(strs, "a", "b", "c")  fmt.Println("string contents:",strs) }}

在上面的程序 names 是 nil,我們已經添加 3 個字符串給 names 。該程序的輸出是

slice is nil going to appendstring contents: [a b c]

也可以使用 ... 運算符將一個切片添加到另一個切片。

package mainimport (  "fmt")func main() {  veggies := []string{"potatoes", "tomatoes", "brinjal"}  fruits := []string{"oranges", "apples"}  food := append(veggies, fruits...)  fmt.Println("food:",food)}

在上述程序的第 10 行,food 是通過 append(veggies, fruits...) 創建。程序的輸出為 food: [potatoes tomatoes brinjal oranges apples] 。

特別需要注意的是如果新切片的長度未超過源切片的容量,則返回源切片,如果追加后的新切片長度超過源切片的容量,則會返回全新的切片。

func main() {  s1 := []int{1,2,3,4,5}  fmt.Printf("s1:%p %d %d %v/n",s1,len(s1),cap(s1),s1)  s2 :=append(s1,6)  fmt.Printf("s3:%p %d %d %v/n",s2,len(s2),cap(s2),s2)  s3 := s1[0:4]  fmt.Printf("s3:%p %d %d %v/n",s3,len(s3),cap(s3),s3)  s4 := append(s3,6)  fmt.Printf("s4:%p %d %d %v/n",s4,len(s4),cap(s4),s4)  fmt.Printf("s1:%p %d %d %v/n",s1,len(s1),cap(s1),s1)  s5 := append(s4,8)  fmt.Printf("s5:%p %d %d %v/n",s5,len(s5),cap(s5),s5)}

切片的函數傳遞

切片包含長度、容量和指向數組第零個元素的指針。當切片傳遞給函數時,即使它通過值傳遞,指針變量也將引用相同的底層數組。因此,當切片作為參數傳遞給函數時,函數內所做的更改也會在函數外可見。

package mainimport (  "fmt")func subtactOne(numbers []int) {  for i := range numbers {    numbers[i] -= 2  }}func main() {  nos := []int{8, 7, 6}  fmt.Println("slice before function call", nos)  subtactOne(nos)                // function modifies the slice  fmt.Println("slice after function call", nos) // modifications are visible outside}

上述程序的行號 17 中,調用函數將切片中的每個元素遞減 2。在函數調用后打印切片時,這些更改是可見的。如果你還記得,這是不同于數組的,對于函數中一個數組的變化在函數外是不可見的。

array before function call [8 7 6] array after function call [6 5 4]

多維切片

類似于數組,切片可以有多個維度。

package mainimport (  "fmt")func main() {    pls := [][]string {      {"C", "C++"},      {"JavaScript"},      {"Go", "Rust"},      }  for _, v1 := range pls {    for _, v2 := range v1 {      fmt.Printf("%s ", v2)    }    fmt.Printf("/n")  }}

程序的輸出為,

C C++ JavaScript Go Rustcopy

切片持有對底層數組的引用。只要切片在內存中,數組就不能被垃圾回收。在內存管理方面,這是需要注意的。讓我們假設我們有一個非常大的數組,我們只想處理它的一小部分。然后,我們由這個數組創建一個切片,并開始處理切片。這里需要重點注意的是,在切片引用時數組仍然存在內存中。

一種解決方法是使用copy 函數 來生成一個切片的副本。這樣我們可以使用新的切片,原始數組可以被垃圾回收。

func copy(dst,src[]T)int`package mainimport (  "fmt")func main() {  s1 :=[]int{1,2,3,4,5}  fmt.Println("s1",s1)  s2 := make([]int,len(s1))  fmt.Println("s2",s2)  copy(s2,s1)  fmt.Println("s2",s2)  s3 :=make([]int,len(s1)-2)  copy(s3,s1);  fmt.Println("s3",s3)  s4 :=make([]int,len(s1)-1)  copy(s4[1:3],s1[2:4]);  fmt.Println("s4",s4)}

打印結果:

s1 [1 2 3 4 5]s2 [0 0 0 0 0]s2 [1 2 3 4 5]s3 [1 2 3]s4 [0 3 4 0]

總結

以上所述是小編給大家介紹的Go基礎Slice教程詳解,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復大家的。在此也非常感謝大家對VEVB武林網網站的支持!


發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
亚洲香蕉成人av网站在线观看_欧美精品成人91久久久久久久_久久久久久久久久久亚洲_热久久视久久精品18亚洲精品_国产精自产拍久久久久久_亚洲色图国产精品_91精品国产网站_中文字幕欧美日韩精品_国产精品久久久久久亚洲调教_国产精品久久一区_性夜试看影院91社区_97在线观看视频国产_68精品久久久久久欧美_欧美精品在线观看_国产精品一区二区久久精品_欧美老女人bb
日本国产欧美一区二区三区| 国产精品美女无圣光视频| 日韩在线视频免费观看| 欧美性xxxx极品高清hd直播| 久久激情视频免费观看| 日韩欧美有码在线| 日韩电影在线观看中文字幕| 成人中文字幕在线观看| 欧美在线国产精品| 国产精品亚洲自拍| 91热福利电影| 欧美激情2020午夜免费观看| 欧美日韩中文字幕在线| 久久精品国产69国产精品亚洲| 日韩av电影中文字幕| 日韩中文字幕国产精品| 成人激情视频在线| 国产玖玖精品视频| 成人激情视频在线| 日韩福利伦理影院免费| 欧美乱大交做爰xxxⅹ性3| 久久久国产精彩视频美女艺术照福利| 26uuu亚洲国产精品| 亚洲一区二区三| 亚洲二区中文字幕| 日韩一区二区三区在线播放| 国产欧美日韩精品专区| 欧美日韩中文字幕综合视频| 欧美成人四级hd版| 国产一级揄自揄精品视频| 日韩精品极品在线观看| 久久精品电影一区二区| 国产一区二区三区四区福利| 这里只有精品丝袜| 91精品国产自产在线观看永久| 午夜精品久久久久久久男人的天堂| 国产精品偷伦免费视频观看的| 精品国产区一区二区三区在线观看| 亚洲精品一区二区久| 久久99热精品这里久久精品| 国产日本欧美视频| 欧美亚洲视频一区二区| 国产精品va在线播放| 九九精品视频在线观看| 国产精品专区第二| 欧美精品做受xxx性少妇| 久久这里只有精品99| 亚洲人成电影网站| 国内精品中文字幕| 欧美日韩一区二区免费视频| 中文字幕欧美日韩va免费视频| 国产日韩欧美成人| 亚洲精品福利在线| 91成人国产在线观看| 最近2019中文字幕大全第二页| 日韩美女中文字幕| 久久久久www| 日本欧美爱爱爱| 国产午夜精品全部视频在线播放| 亚洲欧美日韩一区二区三区在线| 97色在线视频观看| 国产成人综合精品| 91精品国产91久久| 精品久久久久久久久久| 琪琪亚洲精品午夜在线| 成人国内精品久久久久一区| 国产精品久久久久国产a级| 亚洲午夜色婷婷在线| 色噜噜狠狠狠综合曰曰曰| www.日本久久久久com.| 国产欧美亚洲精品| 精品久久久香蕉免费精品视频| 久热精品视频在线| 日本久久中文字幕| 人九九综合九九宗合| 日韩欧美在线观看视频| 38少妇精品导航| 国产精品视频区| 亚洲欧美中文日韩v在线观看| 日本精品一区二区三区在线| 在线成人激情黄色| 亚洲一区亚洲二区亚洲三区| 北条麻妃一区二区三区中文字幕| 亚洲欧美在线播放| 欧美性色19p| 欧美刺激性大交免费视频| 日韩美女av在线| 成人福利网站在线观看| 日韩av在线免费观看| 九九精品视频在线| 91精品免费视频| 九色精品美女在线| 日韩有码在线视频| 久久久久久尹人网香蕉| 色播久久人人爽人人爽人人片视av| 秋霞午夜一区二区| 午夜免费在线观看精品视频| 一区二区欧美日韩视频| 日韩欧美在线视频观看| 欧洲永久精品大片ww免费漫画| 精品久久久久久久久久久| 日韩中文在线不卡| 精品久久久在线观看| 国产精品久久久久久久久久东京| 在线观看精品国产视频| 精品久久中文字幕久久av| 国产成人激情小视频| 欧美福利视频网站| 亚洲午夜av久久乱码| 欧美亚洲国产另类| 精品国产999| 中文字幕亚洲欧美在线| 国产精品电影网站| 成人久久一区二区| 中国人与牲禽动交精品| 亚洲一区二区国产| 亚洲无限乱码一二三四麻| 日本精品中文字幕| 国产精品视频色| 日韩激情av在线播放| 亚洲天堂av综合网| 奇米成人av国产一区二区三区| 国产精品精品国产| 亚洲精品国偷自产在线99热| 欧美高清在线观看| 国产精品91久久久久久| 91久久嫩草影院一区二区| 午夜精品福利电影| 精品调教chinesegay| 日韩欧美黄色动漫| 91久久国产婷婷一区二区| 精品福利在线观看| 亚洲一区999| 欧美日本黄视频| 国产精品久久久久久久久久久久久| 国产精品久久一| 一区二区欧美日韩视频| 日韩中文在线中文网在线观看| 精品毛片三在线观看| 国产情人节一区| 国产一区二区三区免费视频| 2019最新中文字幕| 91日本在线观看| 91免费福利视频| 播播国产欧美激情| 日韩av在线一区| 国产精品成人久久久久| 国产精品夜间视频香蕉| 最新的欧美黄色| 一色桃子一区二区| 亚洲欧洲在线观看| 亚洲最大av网| 成人97在线观看视频| 欧美激情精品久久久久| 亚洲国产天堂久久国产91| 欧美成人免费全部| 国产精品一区二区三区毛片淫片| 国产精品久久97| 国产精品久久久久久久久久尿| 欧美一级大片在线观看| 国产精品久久久久久久电影| 亚洲日本中文字幕免费在线不卡| 精品小视频在线| 色偷偷91综合久久噜噜|