当前位置: 首页 > news >正文

go 语言切片 深入理解实例

go语言切片 深入理解实例

参考https://blog.csdn.net/qq_63730529/article/details/138169657#:~:text=%E4%BD%BF%E7%94%A8%E5%88%87%E7%89%87%E5%AD%97%E9%9D%A2%E9%87%8F%E5%88%9B%E5%BB%BA%E5%88%87

package mainimport "fmt"func SliceRise(s []int) {s = append(s, 0)for i := range s {s[i]++}
}func main() {s1 := []int{1, 2}s2 := s1s2 = append(s2, 3)SliceRise(s1)SliceRise(s2)fmt.Println(s1,s2)
}

1. SliceRise 函数

  • 参数:s []int 是一个整数切片。
  • 功能:
    s = append(s, 0) 将一个 0 追加到切片 s 的末尾。
    for i := range s 遍历切片 s 的每一个元素,并将每个元素的值加 1。

2. main 函数

  • 初始化切片:
    s1 := []int{1, 2} 创建了一个包含两个元素的切片 s1,初始值为 [1, 2]。
    s2 := s1 将 s1 的引用赋值给 s2,这意味着 s1 和 s2 指向同一个内存地址。
  • 修改切片:
    s2 = append(s2, 3) 将 3 追加到 s2 的末尾。由于切片的动态特性,这会导致 s2 分配新的内存地址,但 s1 仍然指向原来的内存地址。因此,s1 和 s2 不再共享相同的内存地址。

3. 结果

[1, 2] [2, 3, 4]

SliceRise 函数在内部对切片进行了修改,但由于 Go 语言的切片传递机制,这些修改不会影响到外部的切片变量。

  • 切片传递机制:
    在 Go 中,切片是按值传递的,这意味着传递给函数的是切片的副本。虽然这个副本可以修改底层的数组,但对切片本身的任何修改(如 append 操作)不会影响到原始切片。

💡 💡 💡 个人理解:
调用SliceRise函数时s和s1、s2是独立的,len(s1)始终是2,len(s2)始终是3

4. AI解答

1. 初始状态

s1 := []int{1, 2}  // len=2, cap=2
s2 := s1           // s2与s1共享底层数组

此时内存布局:

s1 := []int{1, 2}  // len=2, cap=2
s2 := s1           // s2与s1共享底层数组

2. 第一次append

s2 = append(s2, 3)  // 触发扩容

由于原切片容量不足(cap=2,len=2),append会触发扩容,创建新底层数组:

s1 → [1, 2] (原数组不变)
s2 → [1, 2, 3] (新数组,容量=4)

3. 第一次调用SliceRise(s1)

SliceRise(s1)  // 传入s1 = [1, 2]

函数内:

  1. append(s, 0)触发扩容(原容量已满)
    • 创建新数组 [1, 2, 0]
    • 参数s是副本,不影响外部s1
  2. 遍历增加元素值 → [2, 3, 1]
  3. 函数返回后,s1仍保持 [1, 2]

4. 第一次调用SliceRise(s2)

SliceRise(s2)  // 传入s2 = [1, 2, 3]

函数内:

  1. append(s, 0)不扩容(容量足够)
    • 直接修改原数组 → [1, 2, 3, 0]
    • s和s2共享底层数组
  2. 遍历增加元素值:
    • s[0]++ → 1→2
    • s[1]++ → 2→3
    • s[2]++ → 3→4
    • s[3]++ → 0→1
  3. 但s2的len仍是3(因为传入时len=3)
    • 所以s2看到的是 [2, 3, 4]
    • 最后一个元素1不可见(因为len未增加)

5. 最终结果

fmt.Println(s1, s2)  // 输出: [1 2] [2 3 4]

🔥🔥🔥 关键点总结

  1. len不自动扩展:虽然底层数组被修改为 [2, 3, 4, 1],但s2的len仍然是3
  2. 可见范围:s2只能看到前3个元素 [2, 3, 4]
  3. 值传递本质:函数内对切片头的修改(包括len)不会影响外部

⚠️ 这个例子很好地展示了Go切片在函数传递和append操作时的行为特点,是面试中考察切片理解的经典案例。

5. 改进

1. 接收返回值

func SliceRise(s []int) []int {s = append(s, 0)for i := range s {s[i]++}return s
}func main() {s1 := []int{1, 2}s2 := s1s2 = append(s2, 3)s1 = SliceRise(s1)s2 = SliceRise(s2)fmt.Println(s1, s2)
}

结果:

[2 3 1] [2 3 4 1]

2. 传指针

package mainimport "fmt"func SliceRise(s *[]int) {*s = append(*s, 0)for i := range *s {(*s)[i]++}
}func main() {s1 := []int{1, 2}s2 := s1s2 = append(s2, 3)SliceRise(&s1)SliceRise(&s2)fmt.Println(s1, s2)
}

结果:

[2 3 1] [2 3 4 1]

相关文章:

  • Python作业4 文本词云统计,生成词云
  • Android 音频架构全解析:从 AudioTrack 到 AudioFlinger
  • 支付APP如何做好网络安全防护?从技术到用户管理的全链路安全策略
  • Mac mini 安装mysql数据库以及出现的一些问题的解决方案
  • 趣味编程之操作系统趣谈
  • VR拍摄要点与技巧有哪些?有哪些最佳实践?
  • Java面试中问单例模式如何回答
  • 理解.NET Core中的配置Configuration
  • MySQL:Join连接的原理
  • vue3+vite 实现.env全局配置
  • 【jenkins】首次配置jenkins
  • Java Web 之 Servlet 100问
  • SonarQube 集成教程
  • 并发设计模式实战系列(2):领导者/追随者模式
  • SS25001-多路复用开关板
  • 010数论——算法备赛
  • 航电系统通信与数据链技术分析
  • 15 nginx 中默认的 proxy_buffering 导致基于 http 的流式响应存在 buffer, 以 4kb 一批次返回
  • 编程常见错误归类
  • 第五届能源工程、新能源材料与器件国际学术会议(NEMD 2025)
  • 上海与丰田汽车签署战略合作协议,雷克萨斯纯电动汽车项目落子金山
  • 路面突陷大坑致车毁人亡,家属称不知谁来管,长治当地回应
  • 江西省人大教育科学文化卫生委员会主任委员王水平被查
  • 经济日报金观平:拥抱中国就是拥抱确定性
  • 姜仁华任中国水稻研究所所长,胡培松院士卸任
  • 汕头22岁女子手术成功却意外脑死亡,家属称缺氧30分钟医生未发觉