1. 程式人生 > 其它 >12.slice切片宣告、擷取操作

12.slice切片宣告、擷取操作

1.四種宣告方式示例程式碼

slice.go

package chapter09

import "fmt"

// Run
func Run() {
    // 方式1:宣告slice1 是一個切片,並且初始化,預設值是1,2,3,長度是3
    slice1 := []int{1, 2, 3}
    fmt.Printf("len = %d, slice1 = %v\n", len(slice1), slice1)

    // 方式2:宣告slice2一個切片,但是並沒有給slice2分配空間
    var slice2 []int
    slice2 = make([]int, 3) // 通過make開闢3個空間,預設值是0

    slice2[0] = 100
    fmt.Printf("len = %d, slice2 = %v\n", len(slice2), slice2)

    // 方式3:宣告slice3一個切片,同時給slice3分配空間,3個空間,預設值是0
    var slice3 []int = make([]int, 3) // 通過make開闢3個空間,預設值是0

    fmt.Printf("len = %d, slice3 = %v\n", len(slice3), slice3)

    // 方式4:宣告slice4一個切片,同時給slice4分配空間,3個空間,預設值是0,通過 := 推匯出 slice4是一個切片
    slice4 := make([]int, 3) // 通過make開闢3個空間,預設值是0

    fmt.Printf("len = %d, slice4 = %v\n", len(slice4), slice4)

    // 判斷一個切片是否為0
    var slice5 []int
    if len(slice5) == 0 {
        // if slice5 == nil {
        fmt.Println("slice5 是一個空切片")
    } else {
        fmt.Println("slice5 是有空間的")
    }
}

slice_test.go

package chapter09

import "testing"

func TestRun(t *testing.T) {
    Run()
}

執行結果

=== RUN   TestRun
len = 3, slice1 = [1 2 3]
len = 3, slice2 = [100 0 0]
len = 3, slice3 = [0 0 0]
len = 3, slice4 = [0 0 0]
slice5 是一個空切片
--- PASS: TestRun (0.00s)
PASS
ok      

2.切片的追加操作

2.1.示例程式碼

slice2.go

package chapter09

import "fmt"

func Run2() {
    var numbers = make([]int, 3, 5) // 宣告 長度為3 ,容量為5的 int 切片

    fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers)

    // 向 numbers 切片追加一個元素 1, numbers len = 4, [0,0,0,1], cap = 5
    numbers = append(numbers, 1)
    fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers)

    // 向 numbers 切片追加一個元素 1, numbers len = 5, [0,0,0,1.2], cap = 5
    numbers = append(numbers, 2)
    fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers)

    // 向一個容量cap已經滿的slice 追加元素
    numbers = append(numbers, 3)
    fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers), cap(numbers), numbers)

    fmt.Println("----------")
    var numbers2 = make([]int, 3)
    fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers2), cap(numbers2), numbers2)
    numbers2 = append(numbers2, 1)
    fmt.Printf("len = %d, cap = %d, slice = %v\n", len(numbers2), cap(numbers2), numbers2)

}

執行結果

=== RUN   TestRun2
len = 3, cap = 5, slice = [0 0 0]
len = 4, cap = 5, slice = [0 0 0 1]
len = 5, cap = 5, slice = [0 0 0 1 2]
len = 6, cap = 10, slice = [0 0 0 1 2 3]
----------
len = 3, cap = 3, slice = [0 0 0]
len = 4, cap = 6, slice = [0 0 0 1]
--- PASS: TestRun2 (0.00s)
PASS
ok      

圖示解說



動態開闢空間之前

動態開闢空間之後

2.2.總結

3.切片的擷取操作

示例程式碼

slice3.go

package chapter09

import "fmt"

func Run3() {
    s := []int{1, 2, 3} // len = 3 , cap = 3 , [1, 2, 3]

    // [0,2)
    s1 := s[0:2] // [1, 2]
    fmt.Println(s1)

    s1[0] = 100

    fmt.Println("s = ", s)
    fmt.Println("s1 = ", s)

    // copy 可以將底層陣列的slice一起進行拷貝
    s2 := make([]int, 3) // s2 = [0, 0, 0]

    // 將s中的值,依次拷貝到s2中
    copy(s2, s)

    fmt.Println("s2 = ", s2)
}

執行結果

=== RUN   TestRun3
[1 2]
s =  [100 2 3]
s1 =  [100 2 3]
s2 =  [100 2 3]
--- PASS: TestRun3 (0.00s)
PASS
ok  

copy的圖示
copy前

copy後

4.總結

  • 切片的宣告(四種方式)
    • 方式1: slice1 := []int{1, 2, 3} , 宣告+賦值操作
    • 方式2: var slice2 []int
      slice2 = make([]int, 3)
      宣告和空間分配相互獨立,採用make進行切片空間分配
    • 方式3:var slice3 []int = make([]int, 3) 簡化方式2
    • 方式4:slice4 := make([]int, 3) , 使用的是型別推導的方式
  • 切片的追加
    • 如果聲明瞭容量,追加元素後,切片的長度未達到容量的大小,不進行擴容;但是到達容量閾值時,進行2倍的方式進行擴容。
    • 如果沒有指定容量,追加元素,長度到達容量閾值容量,進行2倍的形式擴容。
  • 切片的擷取
    • 擷取的切片指標與元切片共享一個記憶體地址
    • copy 是 為切片,從新開闢新的記憶體地址