我发现 go 好像有个 bug

2024-08-03 15:38:21 +08:00
 liaowb3

我先上代码


type TreeNode struct {
	Val   int
	Left  *TreeNode
	Right *TreeNode
}

func Solution199(root *TreeNode) []int {
	return dfs199(root, []int{})
}	

func dfs199(root *TreeNode,ans []int)[]int{
	if root == nil{
		return ans
	}
	new := append(ans,root.Val)

	right := dfs199(root.Right,new)

	left := dfs199(root.Left,new)


	fmt.Println(root.Val,":")
	if root.Right != nil{
		fmt.Println(root.Right.Val,right)
	}
	if root.Left != nil{
		fmt.Println(root.Left.Val,left)
	}



	result := right
	if len(left) > len(right){
		result = append(result,left[len(right):]...)
	}
	fmt.Println(result)
	return result
}

func main() {
	root := &tree.TreeNode{
		Val: 1,
		Left: nil,
		Right: &tree.TreeNode{
			Val: 5,
			Left: &tree.TreeNode{
				Val: 3,
				Left: &tree.TreeNode{
					Val: 2,
					Left: nil,
					Right: nil,
				},
				Right: &tree.TreeNode{
					Val: 4,
					Left: nil,
					Right: nil,
				},
			},
			Right: nil,
		},
	}
	fmt.Println(tree.Solution199(root))
}

我发现 当递归到 3 这个节点的时候,right 这个数组 通过 dfs199 函数递归后得到是 1534 ,但是当下一个 left 这个数组 通过 dfs199 函数递归后得到 1532 的时候,right 也会跟着变成 1532 这是为什么呢?

3893 次点击
所在节点    Go 编程语言
14 条回复
sagaxu
2024-08-03 16:41:23 +08:00
猜谜语啦,OP 代码的意图是什么?
zzhaolei
2024-08-03 16:54:12 +08:00
这就是 go 的 bug 了?有没有简化的最小复现版?
kingcanfish
2024-08-03 17:07:53 +08:00
为啥不先怀疑自己有没有语法错误或者解法错误,而怀疑是 go 有 bug
还有你这二叉树右视图解法不对吧
````
func rightSideView(root *TreeNode) []int {
var ans []int
dfs(root, 0, &ans)
return ans
}


func dfs(root *TreeNode, level int, ans *[]int) {
if root == nil {
return
}

if level == len(*ans) {
*ans = append(*ans, root.Val)
}
dfs199(root.Right, level+1, ans)
dfs199(root.Left, level+1, ans)
}
```
LittleYangYang
2024-08-03 17:16:40 +08:00
不明白 OP 是什么意图,但盲猜一个是 Slice 底层数组共享了

参考

func Test(t *testing.T) {
base := []int{1, 2, 3}
base1 := append(base, 4)
base2 := append(base1, 5)

fmt.Println("Before:")
fmt.Println(base)
fmt.Println(base1)
fmt.Println(base2)

base1[0] = 0
base2[1] = 0

fmt.Println("After:")
fmt.Println(base)
fmt.Println(base1)
fmt.Println(base2)
}

=== RUN Test
Before:
[1 2 3]
[1 2 3 4]
[1 2 3 4 5]
After:
[1 2 3]
[0 0 3 4]
[0 0 3 4 5]
--- PASS: Test (0.00s)
Kinnice
2024-08-03 18:27:38 +08:00
放心,粗看了一下代码,你的技术水平还不至于可以发现 go 的 bug.
husher123
2024-08-03 18:46:59 +08:00
回答这种问题应该 gpt 很擅长呀~

你遇到的问题是由于 Go 中的切片 (slice) 的底层实现导致的。切片是指向底层数组的引用,因此在函数中对切片的修改会影响到其他引用该切片的变量。具体来说,当你在递归函数中对 right 进行递归调用时,right 和 new 共享同一个底层数组。于是当 left 再次使用 new 时,会改变同一个底层数组,导致 right 的值也被修改。

为了避免这个问题,可以在递归调用前创建新的切片,这样 right 和 left 就不会共享同一个底层数组。

以下是修改后的代码:

https://go.dev/play/p/pHLut5kz-uu

通过使用 make 和 copy 函数,我们创建了一个新的切片 newAns ,从而避免了对同一底层数组的引用。这将解决你所遇到的问题。
cmdOptionKana
2024-08-03 19:13:41 +08:00
OP 是担心不这样问就没人回答问题?
SmartLeo
2024-08-03 20:11:28 +08:00
```
func dfs199(root *TreeNode, ans []int) []int {
if root == nil {
return ans
}
new := append(ans, root.Val)

right := dfs199(root.Right, new)

left := dfs199(root.Left, new)

fmt.Printf("t: ans:%p new:%p\n", ans, new)
fmt.Printf("t: Cap(ans):%d Cap(new):%d\n", cap(ans), cap(new))
fmt.Printf("t: L(ans):%d L(new):%d\n", len(ans), len(new))
fmt.Println(root.Val, ":")
if root.Right != nil {
fmt.Printf("%d %v %p\n", root.Right.Val, right, right)
}
if root.Left != nil {
fmt.Printf("%d %v %p\n", root.Left.Val, left, left)
}

result := right
if len(left) > len(right) {
result = append(result, left[len(right):]...)
}
fmt.Println()
fmt.Println(result)
fmt.Printf("t: result:%p\n\n", result)
return result
}
```
肯定不是 go 的问题啦,是你代码逻辑问题。
你没有完整地了解 slice 的一些特性。

你可以用这段代码看看。

具体到你的问题,显然到 3 那个节点的时候,左右的 slice 是同一个 slice ,而这个 slice 因为调用关系,被最后 left 的处理逻辑最后覆写了。
deplives
2024-08-03 20:44:38 +08:00
众所周知,自认为发现主流语言 bug 的都是_____



学艺不精(俗称菜狗)
PTLin
2024-08-04 10:32:01 +08:00
go 虽然很简单,但是还没简单到学一天就能让你了解到所有 go 的小坑。
dingawm
2024-08-04 13:25:32 +08:00
错误的提问:求大家帮忙看看我的代码有啥问题
正确的提问:我发现 go 好像有个 bug
开个玩笑,楼主也许真的以为是 bug
honjow
2024-08-04 17:22:39 +08:00
在 v2 看到好几个刚学习就嚷嚷发现语言 bug 的帖子了。结果都是自己没搞清楚,大多都是引用相关问题
guanzhangzhang
2024-08-04 19:53:46 +08:00
上次监听 ipv6 地址报错参数错误,我怀疑 golang 的 bug ,然后 dlv 调试下发现错误是_syscall 调用系统返回的,然后用 python 写了个大概逻辑也是一样的报错,最后才发现是内核返回的 ,怀疑有 bug 不应该自己调试下吗
xiaozirun
2024-08-23 19:21:47 +08:00
怀疑题主是想找人帮他找出他写的 bug🤣

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1062240

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX