golang學習筆記 ---數組與切片
數組:
- golang數組包含的每個數據稱為數組元素(element),數組包含的元素個數被稱為數組長度(length)。
- golang數組的長度在定義後不可更改,並且在聲明時可以是一個常量或常量表達式(在編譯期即可計算結果的表達式)。golang數組長度是一個內置常量,可以用len()函數來獲取。
- golang數組是一個值類型,在賦值和作為參數傳遞時都將產生一次復制動作,因此在函數體中無法修改傳入的數組的內容。
數組聲明和初始化
? 數組聲明
? 語法如下
// 數組聲明 var array [n]Type // 數組聲明和初始化 var array [n]Type = [n]Type{v1, v2, ..., vn} var array = [n]Type{v1, v2, ..., vn} array := [n]Type{v1, v2, ..., vn}
? 示例如下
[32]byte // 長度為32的數組,每個元素為一個字節 [2*N] struct { x, y int32 } // 復雜類型數組 [1000]*float64 // 指針數組 [3][5]int // 二維數組 [2][2][2]float64 // 等同於[2]([2]([2]float64))
? 數組常用操作
? 遍歷元素
⊙ 按下標遍歷
√ 使用len()獲取元素個數,然後按下標進行元素遍歷操作。
? 語法如下
for i := 0; i < len(array); i++ { ... }
? 示例如下
package main import "fmt" func main() { array := [5]int{1, 2, 3, 4, 5} for i := 0; i < len(array); i++ { fmt.Println("array[", i, "] =", array[i]) } }
⊙ rang遍歷
√ 可以使用range關鍵字來快速遍歷所有元素。
? 語法如下
for i, v := range array { ... }
? 示例如下
package main import"fmt" func main() { array := [5]int{1, 2, 3, 4, 5} for i, v := range array { fmt.Println("array[", i, "] =", v) } }
數組切片
√ golang數組切片解決的問題:golang數組長度在定義之後無法再次修改,並且數組是值類型,每次傳遞都將產生一份副本。
√ golang數組切片擁有獨立的數據結構,可抽象為3個變量:一個指向原數組的指針,數組切片中元素個數,數組切片分配的存儲空間。
? 創建數組切片
? 基於數組
? 語法如下
var arraySlice []Type = array[first:last]
√ 數組切片的元素範圍為[first, last)。
√ first和last的值可以省略,缺省情況下,first=0,last=len(array)
√ first和last的值必須滿足條件:非負,0 ≤ first ≤ last ≤ len(array),否則編譯器將給出錯誤:
? 示例如下
package main import "fmt" func main() { var array [10]int = [10]int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10} var arraySlice1 []int = array[:] // 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 var arraySlice2 []int = array[:5] // 1, 2, 3, 4, 5 var arraySlice3 []int = array[5:] // 6, 7, 8, 9, 10 var arraySlice4 []int = array[3:8] // 4, 5, 6, 7, 8 fmt.Println("\nElements of arraySlice1: ") for _, v := range arraySlice1 { fmt.Print(v, " ") } fmt.Println("\nElements of arraySlice2: ") for _, v := range arraySlice2 { fmt.Print(v, " ") } fmt.Println("\nElements of arraySlice3: ") for _, v := range arraySlice3 { fmt.Print(v, " ") } fmt.Println("\nElements of arraySlice4: ") for _, v := range arraySlice4 { fmt.Print(v, " ") } fmt.Println() }
? 直接創建
√ golang提供的內置函數make()可以用於靈活地創建數組切片。
? 語法如下
// 創建一個初始元素個數為m的數組切片 arraySlice := make([]Type, m) // 創建一個初始元素個數為m的數組切片,並預留n個元素的存儲空間 arraySlice := make([]Type, m, n) // 直接創建並初始化包含m個元素的數組切片 arraySlice := []Type{v1, v2, ..., vn}
? 示例如下
package main import "fmt" func main() { arraySlice1 := make([]int, 5) // 0 0 0 0 0 arraySlice2 := make([]int, 5, 10) // 0 0 0 0 0 arraySlice3 := []int{1, 2, 3, 4, 5} // 1 2 3 4 5 fmt.Println("\nElements of arraySlice1: ") for _, v := range arraySlice1 { fmt.Print(v, " ") } fmt.Println("\nElements of arraySlice2: ") for _, v := range arraySlice2 { fmt.Print(v, " ") } fmt.Println("\nElements of arraySlice3: ") for _, v := range arraySlice3 { fmt.Print(v, " ") } }
? 基於數組切片
√ 數組切片(newSlice)也可以基於另一個數組切片(oldSlice)創建。
√ newSlice元素範圍可以超過oldSlice所包含的元素個數,只要選擇範圍不超過oldSlice的存儲能力,即cap(oldSlice)的值,那麽這個創建是合法的,newSlice中超出oldSlice元素的部分都會填上0。
√ newSlice的存儲能力等同於oldSlice的存儲能力,即cap(newSlice) = cap(oldSlice)。
? 語法如下
newSlice := oldSlice[first:last] // 0 ≤ first ≤ last ≤ cap(oldSlice)
? 示例如下
package main import "fmt" func main() { oldSlice := make([]int, 5, 10) newSlice := oldSlice[:8] fmt.Println("Length of oldSlice: ", len(oldSlice)) // 5 fmt.Println("Capacity of oldSlice: ", cap(oldSlice)) // 10 fmt.Println("Length of newSlice: ", len(newSlice)) // 8 fmt.Println("Capacity of newSlice: ", cap(newSlice)) // 10 }
? 數組切片的元素個數和存儲能力
√ 與數組相比,數組切片多了一個存儲能力(capacity)的概念,即當前容納的元素個數和分配的空間可以是兩個不同的值。
√ 存儲能力,可以理解為最大容納元素個數,最大容納元素個數減去當前容納元素個數剩下的空間是隱藏的,不能直接使用。如果要往隱藏空間中新增元素,可以使用append()函數。
√ 取得當前容納元素個數可以使用len()函數,取得最大容納元素個數可以使用cap()函數。
package main import "fmt" func main() { arraySlice := make([]int, 5, 10) fmt.Println("len(arraySlice):", len(arraySlice)) // len(arraySlice): 5 fmt.Println("cap(arraySlice):", cap(arraySlice)) // cap(arraySlice): 10 }
? 數組切片常用操作
? 遍歷元素
⊙ 按下標遍歷
√ 與遍歷數組一樣,使用len()獲取元素個數,然後按下標進行元素遍歷操作。
? 語法如下
for i := 0; i < len(arraySlice); i++ { ... }
? 示例如下
package main import "fmt" func main() { arraySlice := []int{1, 2, 3, 4, 5} for i := 0; i < len(arraySlice); i++ { fmt.Println("arraySlice[", i, "] =", arraySlice[i]) } }
⊙ rang遍歷
√ 與遍歷數組一樣,可以使用range關鍵字來快速遍歷所有元素。
? 語法如下
for i, v := range arraySlice { ... }
? 示例如下
package main import "fmt" func main() { arraySlice := []int{1, 2, 3, 4, 5} for i, v := range arraySlice { fmt.Println("arraySlice[", i, "] =", v) } }
? 增加元素
√ 為數組切片增加元素的方法是使用append()函數。
⊙ 追加元素
√ 追加元素時,會自動處理存儲空間不足的問題,如果追加的內容超過當前最大容納元素空間,那麽數組切片會自動分配一塊足夠大的內存。自動分配內存策略為:當前存儲能力 * 2,即cap(arraySlice) * 2。
? 語法如下
arraySlice = append(arraySlice, v1, v2, ..., vn)
? 示例如下
package main import "fmt" func main() { arraySlice := make([]int, 0, 10) arraySlice = append(arraySlice, 1, 2, 3, 4, 5) fmt.Println("len(arraySlice) =", len(arraySlice)) // 5 fmt.Println("cap(arraySlice) =", cap(arraySlice)) // 10 for _, v := range arraySlice { fmt.Print(v, " ") } fmt.Println() arraySlice = append(arraySlice, 6, 7, 8, 9, 10, 11, 12, 13) fmt.Println("len(arraySlice) =", len(arraySlice)) // 13 fmt.Println("cap(arraySlice) =", cap(arraySlice)) // 20 for _, v := range arraySlice { fmt.Print(v, " ") } }
⊙ 追加數組切片
√ 為數組切片arraySlice1追加數組切片arraySlice2時,註意在arraySlice2後面追加三個點,這三個點的意思是把arraySlice2所有元素打散後傳遞給append()函數,這是由於append()函數從第二個參數起的所有參數都必須是待附加的單個元素。
? 語法如下
arraySlice = append(arraySlice, appendSlice...)
? 示例如下
package main import "fmt" func main() { arraySlice := []int{1, 2, 3} appendSlice := []int{4, 5} arraySlice = append(arraySlice, appendSlice...) fmt.Println("len(arraySlice) =", len(arraySlice)) // 5 fmt.Println("cap(arraySlice) =", cap(arraySlice)) // 6 for _, v := range arraySlice { fmt.Print(v, " ") } }
? 刪除元素
√ 數組切片可以動態添加元素,但沒有刪除元素的函數。代替方法是:可以使用數組切片重新組合的方式來刪除一個或多個項。不過從數組切片這種數據結構來看,本身並不適合做刪除操作,所以盡量減少使用。
? 示例如下
package main import "fmt" func main() { s := []int{1, 2, 3, 4, 5, 6} i := 2 s = append(s[:i], s[i+1:]...) fmt.Println(s) // [1 2 4 5 6] }
? 切片之間元素復制
√ golang使用內置函數copy()將數組切片arraySlice2的內容復制到數組切片arraySlice1中。
√ 如果兩個數組切片元素個數不同,那麽就會按其中元素個數較少的數組切片元素個數進行復制操作。
? 示例如下
package main import "fmt" func main() { arraySlice1 := []int{1, 2, 3, 4, 5} arraySlice2 := []int{5, 4, 3} copy(arraySlice2, arraySlice1) // 只會復制arraySlice1的前3個元素到arraySlice2中 fmt.Println(arraySlice2) // [1 2 3] arraySlice3 := []int{1, 2, 3, 4, 5} arraySlice4 := []int{5, 4, 3} copy(arraySlice3, arraySlice4) // 只會復制arraySlice4的3個元素到arraySlice3的前3個位置 fmt.Println(arraySlice3) // [5 4 3 4 5] }
golang學習筆記 ---數組與切片