go20/day02/slice/main.go
yumaojun03 3ddebb3900 ```
docs(slice): 更新切片文档添加冒泡排序示例和图解

- 添加切片作为函数参数的详细说明,包含值传递和引用传递的对比
- 实现MySort(值传递)和MySortV2(引用传递)两个版本的冒泡排序函数
- 新增draw.io图表文件cut.drawio展示切片切割的可视化解释
- 在README.md中添加图片引用和更详细的切片函数参数说明
- 完善main.go中的切片操作示例,包括切割、删除和排序演示
- 修正切片作业描述,明确要求实现两个版本的字符串转大写函数
```
2026-01-11 16:54:23 +08:00

181 lines
5.4 KiB
Go
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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
slice1 = append(slice1, 4, 5)
fmt.Println(slice1, len(slice1), cap(slice1))
// 这里的容器, 不是硬性限制,是超过容量后,底层数组是自动扩容的(重要)
// 扩容: 一般是原来的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. 如果是切片: 底层数组是同一块内存地址空间
*/
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一份 申请一片新的内存来存储这个值, 只copy一层, 浅拷贝
深copy 是递归copy, 需要自己实现, 依赖三方库, 非常耗性能, 一般不推荐使用, 最常见的方式是使用json序列化和反序列化来实现深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)
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]
}
}
}
}