使用 uber-go/dig 在 Golang 中实现依赖注入——基于反射容器,提供 Provide/Invoke、dig.In/dig.Out 参数与结果对象,支持命名依赖等
partition函数必须显式接收low、high参数:空切片时len(arr)-1会越界panic;子切片arr[lo:hi]右边界为hi-1,非len(arr)-1;调用方须保证low≤high。

partition 函数必须带 low/high 参数,不能依赖 len(arr)
直接写 partition(arr []int) 然后用 arr[len(arr)-1] 取 pivot 是高危操作:空切片时 len(arr) 为 0,len(arr)-1 就是 -1,下标 panic 立刻发生。真实递归中传入的总是子切片(如 arr[lo:hi]),它的长度和原始切片无关,但右边界是 hi-1,不是 len(arr)-1。
- 函数签名必须显式接收
low, high int,且调用方保证low - 取 pivot 用
arr[high]最安全——high是有效索引,前提是调用前已校验区间非空 - 分区循环用
for j := low; j ,不是j ,否则 pivot 自身被重复比较
递归终止条件只能是 low >= high,不是 len(arr)
写成 常见错误是这么写:if len(arr) 看似合理,实则错在语义混淆:arr 是子切片,但 len(arr) 返回的是当前切片长度,而你的分区逻辑完全基于 low 和 high 坐标。一旦递归进入 arr[5:6](长度为 1),low=5, high=5,此时 low >= high 成立,应终止;但若用 len(arr) ,虽结果相同,却掩盖了坐标系统一致性这个关键约束。
low 和 high 是唯一可信的边界high 是右闭区间端点,不是长度,所以 quickSort(arr, p+1, high) 合法,而 quickSort(arr[p+1:], ...) 会丢失坐标信息low > high)必须处理,否则某些 pivot 选择策略下可能无限递归别用 append 拼接左右子数组,原地交换才是 Go 的正确姿势
left := append([]int{}, arr[low:p]...),再 append(append(left, pivot), right...)。这根本没改原切片——append 在底层数组容量不足时分配新内存,返回新切片头,原变量仍指向旧地址。你看到的“排序结果”只是临时副本,后续用 sort.Search 查不到任何东西。
arr[i], arr[j] = arr[j], arr[i] 完成,确保修改落在同一底层数组上high-low )直接调用
insertionSort(arr[low:high+1]),传入子切片但不新建rand.Intn(high-low+1) + low,然后立刻 swap 到 high 位,避免后续逻辑假设 pivot 固定在末尾手写快排前先问自己:真需要绕过 sort.Slice 吗?
sort.Slice 不仅防退化、支持泛型、自动处理 nil 和边界,还经过多年生产验证。你手写的版本哪怕只漏一个 if low > high { return },就可能在特定输入下 panic 或死循环。只有三类场景值得手写:算法题强制要求、教学演示分区过程、或需定制不可见行为(比如按绝对值排序且保持原序稳定性)。
sort.Slice 的三个硬约束必须牢记:data 不能为 nil、less 函数必须满足严格弱序、字段访问前要判空(如 a[i].Name != nil)sort.Slice 对 []int 有专门优化路径,手写版除非极致调优,否则常更慢i 而非 i+1,会导致左半段少排一个元素
golang免费学习笔记(深入):立即使用
在学习笔记中,你将探索golang的核心概念和高级技巧!










