速战速决 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

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