关于go里切片作为函数参数时是引用传递还是值传递
问题起因
写一道回溯算法题,把ans二维数组作为函数参数传入,想在函数里面,不停地append,最后返回ans
实际发现ans打印出来是空的,就很奇怪,因为我是事先分配好空间的,理论上不会发生扩容,底层数组是共用的,咋回事
func permute(nums []int) [][]int {
ans := make([][]int, 0, len(nums)*len(nums))
item := append([]int{}, nums...)
backtracking(0, item, nums,&ans)
return ans
}
func backtracking(i int, cur, nums []int, ans [][]int) {
if i == len(nums) {
tmp := slices.Clone(cur)
ans = append(ans, tmp)
return
}
for j:=i;j<len(nums);j++ {
swap(i, j, cur)
backtracking(i+1, cur, nums, ans)
swap(i, j, cur)
}
}
func swap(i,j int, nums []int) {
nums[i], nums[j] = nums[j], nums[i]
}
传递指针问题解决
*ans [][]int
分析原因
切片里不止有底层数组啊,还有Len Cap这些基础数据类型;修改是不可见的
在Go语言中,切片(slice)作为函数参数传递时,是通过值传递的,但这里传递的值是切片头(slice header),其中包含指向底层数组的指针、长度和容量。这意味着函数内部可以通过这个指针修改底层数组的元素,但如果对切片进行追加(append)操作,可能会改变切片头的值(例如长度和指针),这些更改不会反映到外部切片中,因为函数内部操作的是切片头的副本。
import "slices"
func permute(nums []int) [][]int {
ans := make([][]int, 0)
n := len(nums)
// 创建当前排列的副本,用于回溯操作
cur := make([]int, n)
copy(cur, nums)
// 定义闭包函数
var backtrack func(int)
backtrack = func(i int) {
if i == n {
// 将当前排列添加到答案中
tmp := slices.Clone(cur)
ans = append(ans, tmp)
return
}
for j := i; j < n; j++ {
// 交换元素
cur[i], cur[j] = cur[j], cur[i]
backtrack(i + 1)
// 回溯,恢复交换
cur[i], cur[j] = cur[j], cur[i]
}
}
backtrack(0)
return ans
}

浙公网安备 33010602011771号