本文系第十二篇Golang語言學習教程
上一節學習了golang數組的知識,這節開始學習切片的概念應用;首先來看多維陣列
多維陣列
Go語言可以建立多維陣列:
package mainimport "fmt"func test(a [3][2]string) { //定義函數test,輸入值為多維二維數組 a for _, v1 := range a { for _, v2 :=range v1 { fmt.Printf("%s ", v2) //兩次迴圈得到其中一個值並輸出 } fmt.Println("\n") }}func main() { a := [3][2]string{ //定義一個二維數組 {"1x1", "1x2"}, {"2x1", "2x2"}, {"3x1", "3x2"}, } test(a) //調用函數輸出}
上面程式中用簡略文法聲明一個二維數組 a
,使用兩個range迴圈來列印數組的值。
以上程式的輸出為:
1x1 1x2
2x1 2x2
3x1 3x2
另一種聲明文法為一個個添加字串索引來達到初始化二維數組的目的:
func main() { var b [3][2]string b[0][0] = "apple" b[0][1] = "samsung" b[1][0] = "microsoft" b[1][1] = "google" b[2][0] = "AT&T" b[2][1] = "T-Mobile" fmt.Printf("\n") test(b)}
切片
切片是由數組建立的一種方便、靈活、功能強大的封裝。切片本身不擁有任何資料,只是對現有數組引用。
帶有T類型元素的切片由[]T
表示,T代表slice中元素的類型:
package mainimport "fmt"func main(){ a := [6]int{45, 56, 67, 78, 89, 90} var b []int = a[1:5] //建立一個切片 從 a[1] - a[4] fmt.Println(b)}
以上程式中,由a[start:end]
建立了一個從a
數組索引start
到end-1
的切片.
a[1:5]
建立了一個從a[1] - a[4]
的切片。切片b的值為:[56 67 78 89]
還有另一種建立切片的方法:
package mainimport "fmt"func main(){ c := []int{6, 7, 8} //建立一個數組 c ,並返回一個儲存在 c 中的切片引用 fmt.Println(c)}
修改切片
切片不擁有自己的資料,它只是底層數組的一種表現形式。因此對切片進行任何修改都會反映在底層數組中。
package mainimport "fmt"func main(){ num := [...]int{1, 2, 3, 4, 5, 6, 7, 8, 9} //定義數組 num snum := num[2:8] //建立切片從 num[2] - num[7] fmt.Println("before change", num) //輸出改變前 for i := range snum { snum[i]++ //給切片每個參數+1 } fmt.Println("after change", num) //輸出改變後}
以上程式中建立了一個切片snum
,for迴圈將切片的索引逐個遞增,當列印數組時,可以看到對切片的更改反映在了數組中:
before change [1 2 3 4 5 6 7 8 9]
after change [1 2 4 5 6 7 8 9 9]
並且多個切片共用相同的數組時,每個切片所做的更改都將反映在數組中。
定義切片時若不標明開始和結束值,如:num[:]
則開始和結束的預設值分別為 0
和 len (numa)
,即引用整個數組。
切片的長度和容量
slice的長度對應slice中的元素數量;長度不能超過容量。容量一般是從slice的開始為止到底層數組的結束位置。
寫一個月份的程式,來理解slice的長度和容量:
package mainimport "fmt"func main(){ /*一個數組的第一個索引是從0開始,若想跳過0,則用1:的方式,第0個元素會自動初始化為空白字串*/ months := [...]string{1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun", 7: "Jul", 8: "Aug", 9: "Sep", 10: "Oct", 11: "Nov", 12: "Dec"} Q2 := months[4:7] //第二季度 summer := months[6:9] //夏天 fmt.Printf("length of Q2 is %d, capacity is %d\n", len(Q2), cap(Q2)) fmt.Printf("length of summer is %d, capacity is %d", len(summer), cap(summer))}
以上程式中,切片Q2
是由數組months
的索引4
到6
建立的,所以Q2的長度是3
;因為是從數組months
的索引4
開始建立的切片,所以Q2的容量是從4到12
:9;切片sunmer同理。
以上程式運行結果為:
length of Q2 is 3, capacity is 9
length of summer is 3, capacity is 7
如果切片操作超出容量cap(s)上限將會報錯,但是超出長度len(s)上限則意味著擴充了切片,因為新的切片長度會變大。
fmt.Println(summer[:20]) //報錯panic:runtime error: slice bounds out of range
package mainimport "fmt"func main(){ /*一個數組的第一個索引是從0開始,若想跳過0,則用1:的方式,第0個元素會自動初始化為空白字串*/ months := [...]string{1: "Jan", 2: "Feb", 3: "Mar", 4: "Apr", 5: "May", 6: "Jun", 7: "Jul", 8: "Aug", 9: "Sep", 10: "Oct", 11: "Nov", 12: "Dec"} Q2 := months[4:7] //第二季度 summer := months[6:9] //夏天 //fmt.Printf("length of Q2 %d, capacity %d\n", len(Q2), cap(Q2)) //fmt.Printf("length of summer %d, capacity %d", len(summer), cap(summer)) //fmt.Println(summer[:20]) //報錯panic:runtime error: slice bounds out of range endlessSummer := summer[:5] //擴充summer長度,並給切片endlessSummer fmt.Println(endlessSummer) fmt.Printf("the length os endlessSummer is %d, capacity is %d", len(endlessSummer), cap(endlessSummer))}
以上程式中,擴充了summer
的長度,並賦給endlessSummer
以上程式運行結果為:
the length os endlessSummer is 5, capacity is 7
使用make建立切片
func make([]T,len,cap)
[]T 通過傳遞類型,長度和容量來建立切片。容量是選擇性參數, 預設值為切片長度。make 函數建立一個數組,並返回引用該數組的切片。
package mainimport ( "fmt")func main() { i := make([]int, 5, 5) //引用make函數建立切片 fmt.Println(i)}
追加切片元素
數組的長度是固定的,不可以增加,但是切片的長度是可以增加的,使用append
可以將新元素增加到切片上。append 函數的定義是 func append(s[]T,x ... T)[]T
。
x ... T 在函數定義中表示該函數接受參數 x 的個數是可變的。這些類型的函數被稱為可變函數。
package mainimport "fmt"func main(){ cars := []string{"Ferrari", "Honda", "Ford"} //定義切片cars fmt.Println(cars) fmt.Println("old cars length is ", len(cars), "and capacity is ", cap(cars)) //輸出cars的長度和容量 newcars := append(cars, "BYD") //cars 切片增加新元素並定義給另一個切片newcars fmt.Println(newcars) fmt.Println("new cars length is ", len(newcars), "and capacity is ", cap(newcars)) //輸出newcars長度和容量}
以上程式中,原來cars
切片的長度是3,容量是3,我們使用append
函數添加了一個新元素,並賦給另一個切片newcars
。
以上程式運行結果為:
[Ferrari Honda Ford]
old cars length is 3 and capacity is 3
[Ferrari Honda Ford BYD]
new cars length is 4 and capacity is 6
多維切片
類似於數組,切片可以有多個維度。
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 Rust
以上為學習Golang 切片篇