一、说明:
slice 并不是数组或数组指针。它通过内部指针和相关属性引⽤用数组⽚片段,以实现变⻓长⽅方案
二、练习:
代码如下
package main
import (
"fmt"
)
/*
1. slick是引用类型,但自身是结构体,值拷贝专递
2. 熟性len 表示可用元素数量,读写操作不能超过该限制
3. 属性cap 表示最大扩张容量,不能超出数组限制
4. 如果slice == nil,则len、cap 结果都等于0
*/
func main() {
//创建slice
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
//[low : high : max], len = high- low , cap = max - low; tip:创建表达式,使用的是索引
slice1 := data[1:4:5]
slice2 := data[:6:8]
slice3 := data[5:]
slice4 := data[:3]
slice5 := data[:]
fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice1), cap(slice1), slice1)
fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice2), cap(slice2), slice2)
fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice3), cap(slice3), slice3)
fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice4), cap(slice4), slice4)
fmt.Printf("slice1 的len 为:%d, cap 为:%d, value为:%v \n", len(slice5), cap(slice5), slice5)
//读写操作,实际目标是底层数组,需注意索引号的差别
s := data[2:4]
s[0] += 100
s[1] += 200
fmt.Println(s)
fmt.Println(data)
//直接创建slice,自动分配底层数组; 不需要先创建数组, 然后截取一段为slice
s1 := []int{1, 3, 5, 7, 9}
fmt.Printf("s1 的len 为:%d, cap 为:%d, value为:%v \n", len(s1), cap(s1), s1)
//make 创建, 使用基础类型的默认值
s2 := make([]int, 6, 8)
fmt.Printf("s2 的len 为:%d, cap 为:%d, value为:%v \n", len(s2), cap(s2), s2)
s3 := make([]int, 6) //沈略cap, 相当于 cap = len
fmt.Printf("s2 的len 为:%d, cap 为:%d, value为:%v \n", len(s3), cap(s3), s3)
//使用make 动态创建slice, 避免了数组必须用常量做长度的麻烦,还可以用指针直接访问底层数组元素
p := &s1[2]
*p += 10000
fmt.Printf("通过指针访问数组底层元素后,s1 的len 为:%d, cap 为:%d, value为:%v \n\n\n", len(s1), cap(s1), s1)
//[][]T
twoDimensionSlice()
//修改
modify()
//fmt.Println("\nReslice Demo: ")
// resliceDemo()
fmt.Println("\nAppend Demo: ")
appendDemo()
fmt.Println("\nAppend Demo2: ")
appendDemo2()
fmt.Println("\nCopy Demo: ")
copyDemo()
}
// [][]T, 是指元素类型为[]T
func twoDimensionSlice() {
data := [][]int{
[]int{1, 2, 3},
[]int{10, 20, 30},
[]int{100, 200, 300},
}
for i, s := range data {
fmt.Printf("index: %d, slice%d's value: %v \n", i, i, s)
}
}
//
func modify() {
data := [5]struct {
v int
}{}
s := data[:]
data[1].v = 10
s[2].v = 20
fmt.Println(data)
fmt.Printf("%p, %p \n", &data, &data[0])
}
//reslice,指基于已有的slice 创建新的slice对象,以便再cap 允许范围内调整属性
func resliceDemo() {
s := []int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s1 := s[2:5] //[2, 3, 4]
s2 := s1[2:6:7] //[4,5,6,7]
s3 := s2[3:6] //error
fmt.Println("\nresliceDemo: ")
fmt.Printf("s1 的len 为:%d, cap 为:%d, value为:%v \n", len(s1), cap(s1), s1)
fmt.Printf("s2 的len 为:%d, cap 为:%d, value为:%v \n", len(s2), cap(s2), s2)
fmt.Printf("s3 的len 为:%d, cap 为:%d, value为:%v \n", len(s3), cap(s3), s3)
}
//append 向slice 尾部添加元素,返回新的slice 对象
func appendDemo() {
s := make([]int, 0, 5)
fmt.Printf("%p \n", &s)
s2 := append(s, 1)
fmt.Printf("s2 的value 为:%v, s2的地址为: %p \n", s2, &s2)
s2 = append(s2, 11)
fmt.Printf("s2 的value 为:%v, s2的地址为: %p \n", s2, &s2)
fmt.Printf("s的value 为:%v, s2的value 为: %v \n", s, s2)
}
func appendDemo2() {
data := []int{1, 2, 3, 4, 5, 6, 7, 8, 9}
sliceOne := data[1:]
fmt.Printf("sliceOne' value is : %v \n", sliceOne)
sliceOne = append(sliceOne, 10)
fmt.Printf("sliceOne' value is : %v, sliceOne' cap is %d \n", sliceOne, cap(sliceOne))
sliceTwo := append(sliceOne, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20)
fmt.Printf("sliceTwo' value is : %v, sliceTwo' cap is %d \n", sliceTwo, cap(sliceTwo))
fmt.Printf("data' value is %v, data's pointer is %p, data's cap is %d \n", data, &data, cap(data))
}
/*
函数 copy 在两个 slice 间复制数据,复制⻓长度以 len ⼩小的为准。两个 slice 可指向同一底层数组,允许元素区间重叠
*/
func copyDemo() {
data := [...]int{0, 1, 2, 3, 4, 5, 6, 7, 8, 9}
s := data[8:]
s1 := data[:5]
fmt.Printf("s 的value 为:%v, s的地址为: %p \n", s, &s)
fmt.Printf("s1 的value 为:%v, s1的地址为: %p \n", s1, &s1)
//后面的slice 覆盖前面的slice 中对应下标的元素
copy(s1, s)
fmt.Println(s1)
fmt.Println(s)
fmt.Println(data)
}