1. 程式人生 > >golang學習筆記 ---數組與切片

golang學習筆記 ---數組與切片

info lds 位置 內存 print city func 超過 src

數組:

  • 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學習筆記 ---數組與切片