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) , 使用的是类型推导的方式
- 方式1:
- 切片的追加
- 如果声明了容量,追加元素后,切片的长度未达到容量的大小,不进行扩容;但是到达容量阈值时,进行2倍的方式进行扩容。
- 如果没有指定容量,追加元素,长度到达容量阈值容量,进行2倍的形式扩容。
- 切片的截取
- 截取的切片指针与元切片共享一个内存地址
- copy 是 为切片,从新开辟新的内存地址