关于golang的append函数的踩坑

从LeetCode第26题产生的疑问

这篇文章里面提到了关于在函数内部修改数据的情况。但是LeetCode22题中发现append无法在传送变量中进行append。

测试代码

输出结果
[123 456 7] //使用test函数append数字8,但是并没有修改原数据的值
[1 2 3] //同理,只可以在main函数append成功
[1 2 4] //但是可以修改数据的值,append失效的原因待查

package main

import "fmt"

func main() {
	nums := []string{}
	nums = append(nums, "123")
	nums = append(nums, "456")
	nums = append(nums, "7")

	test(nums)
	fmt.Println(nums)

	num := []int{}
	num = append(num, 1)
	num = append(num, 2)
	num = append(num, 3)

	fmt.Println(num)
	test1(num)
	fmt.Println(num)
}


func test1(num []int) {
	// append无法更改值。
	num = append(num, 4)
	num[2] = 4
}


func test(nums []string) {
	nums = append(nums, "8")
}

LeetCode22

在做这个题其中nums = append(nums, s),将所有符合条件的结果存储在nums中,但是return之后nums为空,发现nums无法修改数据的值

package main

import "fmt"

func generateParenthesis(n int) []string {
	nums := make([]string, 0)
	generate("",nums, n, n)
	return nums
}

func generate(s string, nums []string, left int,right int ) {
	if left == 0 && right == 0 {
		nums = append(nums, s)
		return
	}

	if left > 0 {
		generate(s + "(", nums, left - 1, right)
	}
	if right > left {
		generate(s + ")", nums, left, right - 1)
	}
}

func main(){
	x := generateParenthesis(2)
	fmt.Println(x)
}

解决方式

func main() {
	nums := []string{}
	nums = append(nums, "123")
	nums = append(nums, "456")
	nums = append(nums, "7")
	test(&nums)
	fmt.Println(nums)
}

func test(nums *[]string) {
	*nums = append(*nums, "8")
}

原题

https://blog.youkuaiyun.com/csdn_kou/article/details/104307631
为什么返回数值是整数,但输出的答案是数组呢?

请注意,输入数组是以“引用”方式传递的,这意味着在函数里修改输入数组对于调用者是可见的。

你可以想象内部操作如下:

// nums 是以“引用”方式传递的。也就是说,不对实参做任何拷贝
int len = removeDuplicates(nums);

// 在函数里修改输入数组对于调用者是可见的。
// 根据你的函数返回的长度, 它会打印出数组中该长度范围内的所有元素。

例2 LeetCode189

https://leetcode-cn.com/problems/rotate-array
append 拼接过程中重新创建了底层数组,导致函数中的 nums 不再是函数外的 nums,引用失效。
其实也证明go中没有引用类型,因为go不存在引用赋值
测试代码

package main

import "fmt"

func rotate(nums []int, k int)  {
	tx := &nums
	te := reverse(&nums,k)
	*tx = te
	fmt.Println("2", nums)
}

func reverse(nums *[]int, k int) []int{
	*nums = append(*nums, 8)
	return *nums
}

func main(){
	nums := []int{1,2,3,4,5,6,7}
	rotate(nums, 3)
	fmt.Println("1", nums)
}

189题使用这样的方式改变了数组的值

func rotate(nums []int, k int)  {
    k %= len(nums)
    ans := append(nums[len(nums)-k:], nums[:len(nums)-k]...)
    nums = append(nums[:0], ans...)
}

测试是否可以改变原数组。这个小细节可以记一下

package main

import "fmt"

func t(nums []int) {
	// 1 Right
	//ans := append(nums[:2], nums[1])
	//nums = append(nums[:0], ans...)
	// 2 Right
	//ans := append(nums[:2], 1)
	//nums = append(nums[:0], ans...)
	// 3 False
	//ans := append(nums, 1)
	//nums = append(nums[:0], ans...)
	// 4 Right
	//ans := append(nums[:len(nums)-1], 1)
	//nums = append(nums[:0], ans...)
	// 5 Right
	//ans := append(nums[:1], 1)
	//nums = append(nums[:0], ans...)
	// 6 False
	ans := append(nums[:0], 1)
	nums = append(nums[:0], ans...)
}


func main() {
	nums := []int {1,2,3}
	t(nums)
	fmt.Println(nums)
}

copy的值复制

package main

import "fmt"

func test() {
	temp := [][]int {{1,2,3},{2,3}}
	nums := []int {999}

	fmt.Println("temp_init", temp)

	temp = append(temp, nums)
	fmt.Println("temp_append_nums", temp)

	nums[0] = 11111
	//temp [[1 2 3] [2 3]]
	//temp [[1 2 3] [2 3] [999]]
	//temp [[1 2 3] [2 3] [11111]]

	//可以看到append不是值拷贝,如果只想值拷贝使用copy函数
	fmt.Println("temp_change_nums_print_temp", temp)


	fmt.Println(nums)
}
func main() {
	temp := [][]int {{1,2,3},{2,3}}
	nums := []int {999}

	fmt.Println("temp_init", temp)
	r := make([]int, len(nums))
	copy(r, nums)
	temp = append(temp, r)
	fmt.Println("temp_append_nums", temp)

	nums[0] = 11111
	fmt.Println("temp_change_nums_print_temp", temp)
	fmt.Println(nums)
}

评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值