Skip to content

Daily Study

更新: 10/6/2025 字数: 0 字 时长: 0 分钟

Daily Plan

#todo

  • [ ]

闭包陷阱

从该语句出发:ans = append(ans, append([]int(nil), path...))

语句的含义是:path 切片的内容复制一份,并将这份副本作为一个新的元素添加到 ans(结果切片)中。

主要包括两个操作:

  • append([]int(nil),path...):把path的所有内容复制到新建的[]int(nil)切片上
  • ans = append(ans , ):追加到ans数组中

这条语句的使用场景几乎都出现在递归或回溯算法中(比如路径查找、组合生成等),其中 path 是一个在整个递归过程中被重复使用和修改的工作切片。

如果不创建副本,而是直接将 path 添加到 ans 中,就会产生著名的 “切片闭包陷阱”ans = append(ans, path)。由于 ans 中的元素和当前的 path 共享同一个底层数组,当你修改 path 时,ans 中存储的所有旧结果也会被一同修改!

详解一下其中的 []int(nil):

  1. []int:切片类型字面量:[]int 本身是 Go 语言中表示 int 类型的切片 的类型字面量。
  2. (nil):零值 nil 是 Go 语言中许多引用类型(如指针、切片、映射、通道、函数和接口)的零值
  3. []int(nil):类型转换 (Type Conversion)

这整个表达式使用了 Go 的类型转换语法:T(V),其中 T 是目标类型,而 V 是要转换的值。 在这里:

  • 目标类型 T[]int (切片)。
  • 值 Vnil (切片的零值)。

Go 语言允许将 nil 这个引用类型的零值显式地转换为任何引用类型(如切片、映射、指针等)。

虽然 []int(nil)make([]int, 0) 都会创建一个长度和容量都为 0 的空切片,但它们在底层存储上略有不同:

表达式底层指针内存分配优势
[]int(nil)nil没有底层数组分配最轻量级,通常用于函数返回值或比较。
make([]int, 0)nil底层数组(虽然长度为 0)底层指针非 nil,有时更适合作为函数参数。

在您的原始代码 append([]int(nil), path...) 中,使用 []int(nil) 确保了 append 操作是从一个完全独立、零开销的切片开始构建副本。

菜就多练

本站访客数 人次 本站总访问量