diff --git a/day02/slice/README.md b/day02/slice/README.md index debe773..8d23e8e 100644 --- a/day02/slice/README.md +++ b/day02/slice/README.md @@ -177,7 +177,7 @@ fmt.Println(s2) // [99 2 3] ```go s := []int{0, 1, 2, 3, 4, 5} -// 创建子切片:s[low:high] (不包括high) +// 创建子切片:s[low:high] (不包括high) [start: end) sub1 := s[1:4] // [1, 2, 3] fmt.Println(sub1) @@ -187,30 +187,46 @@ sub3 := s[2:] // [2, 3, 4, 5] sub4 := s[:] // [0, 1, 2, 3, 4, 5] 复制整个切片 ``` -## 切片作为函数参数 +![alt text](image-6.png) + +## 切片作为函数参数 (重点: 90%) **原理**:切片作为参数传递时,是引用传递,函数内修改会影响调用者。高效但需注意副作用。 ```go -func sum(nums []int) int { - total := 0 - for _, num := range nums { - total += num - } - return total +// 冒泡排序: 值传递 +// 返回一个新的切片(排序的结果) +func MySort(arr []int) []int { + // 冒泡排序 + for i := 0; i < len(arr)-1; i++ { + for j := 0; j < len(arr)-1-i; j++ { + if arr[j] > arr[j+1] { + // 值交换: a, b = b, a + arr[j], arr[j+1] = arr[j+1], arr[j] + } + } + } + return arr } -func main() { - s := []int{1, 2, 3, 4, 5} - result := sum(s) - fmt.Println(result) // 15 +// 冒泡排序: 引用传递 +// 直接修改传入的切片(在原切片上进行排序) +func MySortV2(arr *[]int) { + // 冒泡排序 + for i := 0; i < len(*arr)-1; i++ { + for j := 0; j < len(*arr)-1-i; j++ { + if (*arr)[j] > (*arr)[j+1] { + // 值交换: a, b = b, a + (*arr)[j], (*arr)[j+1] = (*arr)[j+1], (*arr)[j] + } + } + } } ``` ## 总结 切片是 Golang 中比较有特色的一种数据类型,既为我们操作集合类型的数据提供了便利的方式,是又能够高效的在函数间进行传递,因此在代码中切片类型被使用的相当广泛 - ## 作业 请同学们完成以下切片练习题,以巩固对Go语言切片的理解: @@ -231,6 +247,6 @@ func main() { 创建一个切片,拷贝到另一个切片,修改原切片,验证拷贝是否独立。 6. **函数参数** - 编写一个函数,接受字符串切片作为参数,将所有字符串转换为大写并返回新切片。 + 编写一个函数,接受字符串切片作为参数,将所有字符串转换为大写并返回新切片, 需要实现2个版本, 1.一个值版本, 2. 指针版本。 请将代码写在 `main.go` 文件中,并运行测试。 diff --git a/day02/slice/cut.drawio b/day02/slice/cut.drawio new file mode 100644 index 0000000..13389cf --- /dev/null +++ b/day02/slice/cut.drawio @@ -0,0 +1,110 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/day02/slice/image-5.png b/day02/slice/image-5.png new file mode 100644 index 0000000..284f1bc Binary files /dev/null and b/day02/slice/image-5.png differ diff --git a/day02/slice/image-6.png b/day02/slice/image-6.png new file mode 100644 index 0000000..6807035 Binary files /dev/null and b/day02/slice/image-6.png differ diff --git a/day02/slice/main.go b/day02/slice/main.go index be0f611..3f095c3 100644 --- a/day02/slice/main.go +++ b/day02/slice/main.go @@ -86,7 +86,6 @@ func main() { 注意: 数组是引用类型吗? 不是 1. 如果是数组: 是2块隔离的内存地址空间(线性分配) 2. 如果是切片: 底层数组是同一块内存地址空间 - 浅拷贝: 赋值 底层数据没有copy一份, 还是指向同一块内存地址空间 */ fmt.Println("== 切片是一种引用类型 ==") slice7 := []int{1, 2, 3} @@ -101,7 +100,8 @@ func main() { 切片的拷贝 如果希望把 底层arry里面的数据copy到另一个切片中 使用内置函数: copy(目标切片, 源切片) - 深拷贝: 底层数据已copy一份 申请一片新的内存来存储这个值 + 拷贝: 底层数据已copy一份 申请一片新的内存来存储这个值, 只copy一层, 浅拷贝 + 深copy 是递归copy, 需要自己实现, 依赖三方库, 非常耗性能, 一般不推荐使用, 最常见的方式是使用json序列化和反序列化来实现深copy */ fmt.Println("== 切片的拷贝 ==") slice9 := make([]int, len(slice7)) @@ -110,4 +110,71 @@ func main() { slice9[0] = 2000 fmt.Println("slice7:", slice7) fmt.Println("slice9:", slice9) + + fmt.Println("== 切片 切割(共享底层数组) ==") + slice10 := []int{1, 2, 3} + fmt.Println("slice10:", slice10) + slice11 := slice10[1:3] + fmt.Println("slice11:", slice11) + slice11[0] = 200 + fmt.Println("slice10:", slice10) + fmt.Println("slice11:", slice11) + + /* + 切片的删除 + 切片的删除是通过切片操作实现的,即使用切片语法来移除指定范围的元素。 + */ + fmt.Println("== 切片的删除 ==") + slice12 := []int{1, 2, 3, 4, 5} + fmt.Println("slice12:", slice12) + + // 1. 从老切片中过滤出需要的元素 + // 2. 重新组合成一个新的切片 + // 删除索引为2的元素 (值3) + slice12 = append(slice12[:2], slice12[3:]...) + fmt.Println("slice12:", slice12) + + /* + 函数作为参数 + */ + fmt.Println("== 函数作为参数 ==") + slice13 := []int{5, 3, 4, 1, 2} + fmt.Println("排序前:", slice13) + // 值传递 + slice13_sorted := MySort(slice13) + fmt.Println("排序后(值传递):", slice13_sorted) + fmt.Println("原切片slice13:", slice13) + + // 引用传递 + MySortV2(&slice13) + fmt.Println("排序后(引用传递):", slice13) +} + +// 冒泡排序: 值传递 +// 返回一个新的切片(排序的结果) +func MySort(arr []int) []int { + // 冒泡排序 + for i := 0; i < len(arr)-1; i++ { + for j := 0; j < len(arr)-1-i; j++ { + if arr[j] > arr[j+1] { + // 值交换: a, b = b, a + arr[j], arr[j+1] = arr[j+1], arr[j] + } + } + } + return arr +} + +// 冒泡排序: 引用传递 +// 直接修改传入的切片(在原切片上进行排序) +func MySortV2(arr *[]int) { + // 冒泡排序 + for i := 0; i < len(*arr)-1; i++ { + for j := 0; j < len(*arr)-1-i; j++ { + if (*arr)[j] > (*arr)[j+1] { + // 值交换: a, b = b, a + (*arr)[j], (*arr)[j+1] = (*arr)[j+1], (*arr)[j] + } + } + } }