1.Golang中的陣列
陣列是一種具有固定長度的基本資料結構,在golang中與C語言一樣陣列一旦創建了它的長度就不允許改變,陣列的空余位置用0填補,不允許陣列越界,
陣列的一些基本操作:
1.創建陣列:
func main() {
var arr1 = [...]int{1,2,3,4} //[...]默認為元素的數量即為陣列的長度
fmt.Println(len(arr1)) //4
arr1[4] = 5 //panic 陣列越界
fmt.Println(arr1)
var arr2 = [10]int{1,2,3,4}
fmt.Println(arr2) //[1 2 3 4 0 0 0 0 0 0]
}
2.陣列是值拷貝傳遞:
func main() {
var arr = [10]int{4,5,7,11,8,9}
fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,0]
//驗證陣列是值拷貝傳遞
AddOne(arr)
fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,0]
}
func AddOne(arr [10]int){
arr[9] = 999999
fmt.Println(arr) //[4,5,7,11,8,9,0,0,0,999999]
}
2.Golang中的切片(slice)
1.首先看看slice的原始碼結構:
type slice struct {
array unsafe.Pointer
len int
cap int
}
slice是一個特殊的參考型別,但是它自身也是個結構體
屬性len表示可用元素數量,讀寫操作不能超過這個限制,不然就會panic
屬性cap表示最大擴張容量,當然這個擴張容量也不是無限的擴張,它是受到了底層陣列array的長度限制,超出了底層array的長度就會panic
2.slice的創建:
func main() {
var arr = [...]int{0,1,2,3,4,5,6}
slice1 := arr[1:4:5] //{low:high:max} 最多再擴張一個元素
//max超出 len(arr)
//slice2 := arr[1:4:7] //panic
fmt.Println(slice1) //[1,2,3]
slice3 := slice1[1:3:4] //[2,3] 大于4會panic
fmt.Println(slice3)
}
上面代碼中創建了一個長度為7的陣列arr,同時創建一個基于陣列arr的切片slice1,切片參考了陣列的index=1到index=3之間的元素,同時也允許切片最大擴張1個元素大小的空間,如果這個擴張空間大于7那么程式就會panic,最后創建了一個基于slice1延申的一個切片slice2,它參考了切片的index=1到index=3之間的元素,由于slice1最大擴容1個元素,因此slice2也最多擴容一個元素,超過了會panic,

創建基于底層陣列的slice,其cap取值在: len<=cap<=len(arr)之間
創建基于一個切片的slice,其cap取值在: len(slice1)<=cap<=cap(slice1)之間
3.slice使用make創建
func main() {
var slice = make([]int,3,5) //len=3,cap=5
fmt.Println(slice) //[0,0,0]
slice2:=slice[:5] //slice實作了對slice的擴容,切片長度變為5
fmt.Println(slice2) //[0,0,0,0,0]
}
4.切片作為引數傳遞
func main() {
var slice = make([]int,3,5) //len=3,cap=5
fmt.Println(slice) //[0,0,0]
slice2:=slice[:5] //slice實作了對slice的擴容,切片長度變為5
fmt.Println(slice2) //[0,0,0,0,0]
slice[0] = 999 //這里slice和slice的index=0位置都是999 因為他們參考的底層陣列的index=0位置都是999
fmt.Println(slice)
fmt.Println(slice2)
AddOne(slice) //[8888,0,0]
fmt.Println(slice) //[8888,0,0]
fmt.Println(slice2) //[8888,0,0,0]
}
func AddOne(s []int){
s[0] = 8888
fmt.Println(s)
}
因為切片是個參考型別,所以它作為引數傳遞給函式,函式操作的實質是底層陣列
3.Golang中的切片追加append()
func main() {
var arr = [...]int{1,2,3,4}
fmt.Println(arr) //[1,2,3,4]
slice := arr[:]
fmt.Println(slice) //[1,2,3,4]
slice = append(slice,[]int{5,6,7}...) //此時slice的參考地址已經發生改變了,它參考的底層陣列再也不是arr了,而是一個新的陣列newarr[1,2,3,4,5,6,7]
fmt.Println(slice) //[1,2,3,4,5,6,7]
//驗證slice參考的地址已經發生改變
slice[0] = 666
fmt.Println(arr) //[1,2,3,4]
fmt.Println(slice) //[666,2,3,4,5,6,7]
}
這里由于slice進行追加的元素超出了原來陣列的大小,因此go內部會幫我們創建一個新的底層陣列,而slice的參考地址不再是arr了,變成了新創建的陣列,
還有一種情況就是當slice進行追加的時候沒有超出原來陣列的大小的時候,其參考地址沒有發生改變,
func main() {
var arr = [6]int{1,2,3,4}
fmt.Println(arr) //[1,2,3,4,0,0]
slice := arr[:4]
fmt.Println(slice) //[1,2,3,4]
slice = append(slice,5)
fmt.Println(arr) //[1,2,3,4,5,0]
fmt.Println(slice) //[1,2,3,4,5]
}
4.總結
(1)go是有陣列的,只是平時用切片比較多,陣列大小一旦創建就不能改變,陣列長度大于元素個數的時候會用0補位,這跟其他語言是相通的,
(2)切片slice可以看作是對陣列的一切操作,它是一個參考資料型別,其資料結構包括底層陣列的地址,以及元素可操作長度len或可擴容長度cap,
(3)要想突破slice的擴容cap限制進行無限擴容就需要使用append()函式進行操作,如果append追加的元素后slice的總長度不超過底層陣列的總長度,那么slice參考的地址不會發生改變,反之參考地址會 變成新的陣列的地址,
(4)slice是一個抽象的概念,它存在的意義在于方便對一個順序結構進行一些方便操作,例如查找,排序,追加等等,這個類似于python的list,
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/38551.html
標籤:Go
下一篇:golang單元測驗簡述
