diff --git a/day02/slice/README.md b/day02/slice/README.md index b86cf63..debe773 100644 --- a/day02/slice/README.md +++ b/day02/slice/README.md @@ -118,22 +118,7 @@ s = append(s, 4, 5) fmt.Println(s) // [1 2 3 4 5] ``` -## 通过切片创建新的切片 - -**原理**:切片操作创建新的切片视图,共享底层数组。新切片的长度是high-low,容量是原容量减去low。 - -```go -s := []int{0, 1, 2, 3, 4, 5} - -// 创建子切片:s[low:high] (不包括high) -sub1 := s[1:4] // [1, 2, 3] -fmt.Println(sub1) - -// 省略索引 -sub2 := s[:3] // [0, 1, 2] -sub3 := s[2:] // [2, 3, 4, 5] -sub4 := s[:] // [0, 1, 2, 3, 4, 5] 复制整个切片 -``` +![alt text](image-2.png) ## 遍历切片 @@ -166,6 +151,9 @@ fmt.Println(s1) // [99 2 3] s1 也被修改了 fmt.Println(s2) // [99 2 3] ``` +![alt text](image-3.png) + + ## 切片拷贝 **原理**:使用copy函数进行深拷贝,创建独立的数据副本。修改拷贝后的切片不会影响原切片。 @@ -180,6 +168,25 @@ fmt.Println(s1) // [1 2 3] s1 不变 fmt.Println(s2) // [99 2 3] ``` +![alt text](image-4.png) + +## 通过切片创建新的切片 + +**原理**:切片操作创建新的切片视图,共享底层数组。新切片的长度是high-low,容量是原容量减去low。 + +```go +s := []int{0, 1, 2, 3, 4, 5} + +// 创建子切片:s[low:high] (不包括high) +sub1 := s[1:4] // [1, 2, 3] +fmt.Println(sub1) + +// 省略索引 +sub2 := s[:3] // [0, 1, 2] +sub3 := s[2:] // [2, 3, 4, 5] +sub4 := s[:] // [0, 1, 2, 3, 4, 5] 复制整个切片 +``` + ## 切片作为函数参数 **原理**:切片作为参数传递时,是引用传递,函数内修改会影响调用者。高效但需注意副作用。 diff --git a/day02/slice/append.drawio b/day02/slice/append.drawio new file mode 100644 index 0000000..c672274 --- /dev/null +++ b/day02/slice/append.drawio @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/day02/slice/image-2.png b/day02/slice/image-2.png new file mode 100644 index 0000000..9b55db6 Binary files /dev/null and b/day02/slice/image-2.png differ diff --git a/day02/slice/image-3.png b/day02/slice/image-3.png new file mode 100644 index 0000000..3decc51 Binary files /dev/null and b/day02/slice/image-3.png differ diff --git a/day02/slice/image-4.png b/day02/slice/image-4.png new file mode 100644 index 0000000..a7081fb Binary files /dev/null and b/day02/slice/image-4.png differ diff --git a/day02/slice/main.go b/day02/slice/main.go index d6f05b2..be0f611 100644 --- a/day02/slice/main.go +++ b/day02/slice/main.go @@ -3,8 +3,12 @@ package main import "fmt" func main() { + /* + 声明与赋值 + */ // 1. 声明切片, 切片不是一个值,是一个boxed结构体, array unsafe.Pointer // 数组指针 // 底层数组的长度: 容量10, 当前有几个元素3 + // 需要考虑性能时,这个常用 slice1 := make([]int, 3, 5) fmt.Println(slice1, len(slice1), cap(slice1)) // 底层数组的长度: 容量10, 当前有几个元素3 @@ -14,4 +18,96 @@ func main() { // 扩容: 一般是原来的2倍, 新申请一块更大的数组, 把老数据copy过去 slice1 = append(slice1, 6) fmt.Println(slice1, len(slice1), cap(slice1)) + + // 2. 声明并赋值 (不常用) + var slice2 []int + slice2 = []int{1, 2, 3, 4, 5} + fmt.Println(slice2, len(slice2), cap(slice2)) + + // 3. 声明赋值放在一起 (常用) + var slice3 []int = []int{1, 2, 3, 4, 5} + fmt.Println(slice3, len(slice3), cap(slice3)) + + // 4. 快捷声明赋值 (常用) + slice4 := []int{1, 2, 3, 4, 5} + fmt.Println(slice4, len(slice4), cap(slice4)) + + /* + 切片的访问 + 1. 通过下标(元素的索引)访问切片元素 + 2. 元素值修改,直接通过下标赋值即可 + */ + fmt.Println("slice4[0]=", slice4[0]) + slice4[0] = 100 + fmt.Println("slice4[0]=", slice4[0]) + + /* + 切片中添加元素 + append(切片变量, 元素1, 元素2, ...) + 注意append 后 是参数一个新的切片变量, 所以要接收返回值 + 动作: 申请了新的底层数组, 把老数据copy过去, 然后添加新的元素 + append的元素如果超过容器,会触发地址扩容, 新的数组 + */ + slice4_v2 := append(slice4, 6, 7, 8) + fmt.Println("slice4:", slice4, len(slice4), cap(slice4)) + fmt.Println("slice4_v2:", slice4_v2, len(slice4_v2), cap(slice4_v2)) + + /* + 1. nil 切片: 没有分配内存(array指针是nil), 长度和容量都是0 + 2. 空切片 + 切片时一个应用类型(盒子) + */ + var slice5 []int // nil 切片 + fmt.Println(slice5, len(slice5), cap(slice5)) + slice5 = append(slice5, 10, 11, 12) + fmt.Println(slice5, len(slice5), cap(slice5)) + + slice6 := []int{} // 空切片 + fmt.Println(slice6, len(slice6), cap(slice6)) + slice6 = append(slice6, 10) + fmt.Println(slice6, len(slice6), cap(slice6)) + + /* + 切片的遍历 + 1. for 循环遍历, 实际上遍历的也是底层的数组 + 2. for range 遍历 + */ + fmt.Println("== 切片的遍历: for ==") + for i := 0; i < len(slice4_v2); i++ { + fmt.Printf("slice4_v2[%d]=%d\n", i, slice4_v2[i]) + } + fmt.Println("== 切片的遍历: for range (推荐) ==") + for index, value := range slice4_v2 { + fmt.Printf("slice4_v2[%d]=%d\n", index, value) + } + + /* + 切片是一种引用类型 + 注意: 数组是引用类型吗? 不是 + 1. 如果是数组: 是2块隔离的内存地址空间(线性分配) + 2. 如果是切片: 底层数组是同一块内存地址空间 + 浅拷贝: 赋值 底层数据没有copy一份, 还是指向同一块内存地址空间 + */ + fmt.Println("== 切片是一种引用类型 ==") + slice7 := []int{1, 2, 3} + slice8 := slice7 + fmt.Println("slice7:", slice7) + fmt.Println("slice8:", slice8) + slice8[0] = 1000 + fmt.Println("slice7:", slice7) + fmt.Println("slice8:", slice8) + + /* + 切片的拷贝 + 如果希望把 底层arry里面的数据copy到另一个切片中 + 使用内置函数: copy(目标切片, 源切片) + 深拷贝: 底层数据已copy一份 申请一片新的内存来存储这个值 + */ + fmt.Println("== 切片的拷贝 ==") + slice9 := make([]int, len(slice7)) + copy(slice9, slice7) + fmt.Println("slice9:", slice9) + slice9[0] = 2000 + fmt.Println("slice7:", slice7) + fmt.Println("slice9:", slice9) } diff --git a/day02/slice/ref.drawio b/day02/slice/ref.drawio new file mode 100644 index 0000000..967bab4 --- /dev/null +++ b/day02/slice/ref.drawio @@ -0,0 +1,165 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file