速戰速決 go - go 容器: 切片(通過範圍獲取切片,切片的構造,切片數據的添加/複製/刪除,數組和切片的區別)

速戰速決 go https://github.com/webabcd/GoSample
作者 webabcd

速戰速決 go - go 容器: 切片(通過範圍獲取切片,切片的構造,切片數據的添加/複製/刪除,數組和切片的區別)

示例如下:

container/slice.go

// go 容器 - 切片(通過範圍獲取切片,切片的構造,切片數據的添加/複製/刪除,數組和切片的區別)

// 數組是內存中的一段連續空間,切片是對數組的某一段連續空間的引用
// 數組是固定長度的,切片是長度可變的
// 數組是指針指向的值,切片是一個指針(也就是所謂的數組是值類型,切片是引用類型)

package container

import (
	"fmt"
	"reflect"
)

func SliceSample() {
	slice_sample1()
	slice_sample2()
	slice_sample3()
	slice_sample4()
	slice_sample5()
	slice_sample6()
}

// 從數組或切片中獲取指定範圍的切片
func slice_sample1() {
	var a = [5]int{1, 2, 3, 4, 5}

	// 獲取指定位置範圍的切片(左閉右開原則,即包括左邊,不包括右邊)
	fmt.Println(a[0:3]) // [1 2 3]
	fmt.Println(a[:5])  // [1 2 3 4 5]
	fmt.Println(a[0:])  // [1 2 3 4 5]
	fmt.Println(a[0:0]) // []
	fmt.Println(a[:])   // [1 2 3 4 5]

	// a 是數組,它是固定長度的
	fmt.Println(reflect.TypeOf(a)) // [5]int
	// a[:] 是切片,它的長度是可變的
	fmt.Println(reflect.TypeOf(a[:])) // []int

	// 注:切片之間是不能通過 == 做相等判斷的,下面這句會編譯時報錯
	// fmt.Println(a[:] == a[:])
}

// 構造切片
func slice_sample2() {
	// 構造一個切片
	//   第 2 個參數表示切片初始化時元素的個數
	//   第 3 個參數表示初始化時,爲切片分配的初始空間的長度
	//     如果不指定此參數,則其值同第 2 個參數
	//     後續,如果切片中的元素個數發生了變化,系統會根據它自己的邏輯決定是否重新分配空間
	var a []int = make([]int, 2)
	b := make([]int, 2, 10)

	// 構造一個切片,並初始化(與數組的區別是 [] 裏面啥都沒有)
	c := []int{0, 0}

	// len() - 獲取切片的長度
	// cap() - 獲取切片的佔用空間的長度
	fmt.Println(a, b, c, len(a), len(b), len(c), cap(a), cap(b), cap(c)) // [0 0] [0 0] [0 0] 2 2 2 2 10 2
}

// 在切片的頭部或尾部添加數據
func slice_sample3() {
	a := []int{}

	// 在尾部添加元素
	a = append(a, 0, 1, 2)
	a = append(a, []int{3, 4, 5}...)
	fmt.Println(a) // [0 1 2 3 4 5]

	// 在開頭添加元素
	a = append([]int{-3, -2, -1}, a...)
	fmt.Println(a) // [-3 -2 -1 0 1 2 3 4 5]
}

// 切片的複製
func slice_sample4() {
	a := []int{1, 2, 3, 4, 5}
	b := make([]int, 10)
	c := make([]int, 10)

	// 將 a 複製給 b(返回值爲複製的元素個數)
	d := copy(b, a)

	// 將 a[2:5] 複製給 c[2:5](返回值爲複製的元素個數)
	e := copy(c[2:5], a[2:5])

	fmt.Println(a, b, c, d, e) // [1 2 3 4 5] [1 2 3 4 5 0 0 0 0 0] [0 0 3 4 5 0 0 0 0 0] 5 3
}

// 切片中元素的刪除
func slice_sample5() {
	a := []int{1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18}
	fmt.Println(a) // [1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18]

	a = a[2:]        // 刪除開頭 2 個元素
	a = a[:len(a)-2] // 刪除尾部 2 個元素
	fmt.Println(a)   // [3 4 5 6 7 8 9 10 11 12 13 14 15 16]

	a = append(a[:0], a[2:]...) // 刪除開頭 2 個元素
	a = a[:copy(a, a[2:])]      // 刪除開頭 2 個元素
	fmt.Println(a)              // [7 8 9 10 11 12 13 14 15 16]

	a = append(a[:2], a[5:]...)  // 刪除索引位置 2 到 4 之間的 3 個元素
	a = a[:2+copy(a[2:], a[5:])] // 刪除索引位置 2 到 4 之間的 3 個元素
	fmt.Println(a)               // [7 8 15 16]
}

// 數組和切片的區別
func slice_sample6() {
	// 數組,固定長度
	a := [3]int{1, 2, 3}
	// 切片,長度可變
	b := []int{1, 2, 3}

	// 數組 a 是指針指向的值
	// 切片 b 是一個指針
	fmt.Printf("%v, %v, %T, %T, %p, %p\n", a, b, a, b, &a, b) // [1 2 3], [1 2 3], [3]int, []int, 0xc00000e168, 0xc00000e180

	// 切片是對數組的一段連續區域的引用
	c := a[:2]
	d := a[1:]
	// 所以指針 &a 和指針 c 是一樣的,而指針 &a 和指針 d 是不一樣的
	fmt.Printf("%v, %v, %v, %p, %p, %p\n", a, c, d, &a, c, d) // [1 2 3], [1 2], [2 3], 0xc00000e168, 0xc00000e168, 0xc00000e170
}

速戰速決 go https://github.com/webabcd/GoSample
作者 webabcd

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章