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