gpt4 book ai didi

Golang range through channel 在实现堆排列算法时具有奇怪的行为

转载 作者:IT王子 更新时间:2023-10-29 01:41:33 26 4
gpt4 key购买 nike

我正在尝试实现 Heap's Algorithm在去使用 channel 。当仅在屏幕上打印 slice 时,下面的代码工作正常,但是当使用 channel 将数组传递到主函数上的 for/range 循环时,会发生一些意外行为,并且 slice/数组以口是心非的方式打印,并且并非所有排列都是发送。我想也许我在主要功能能够打印结果之前关闭 channel ,但我不希望双重打印。为什么会发生这种情况,我该如何让它发挥作用。

package main

import "fmt"

func perm(a []int64) {
var n = len(a)
var c = make([]int, n)
fmt.Println(a)
i := 0
for i < n {
if c[i] < i {
if i%2 == 0 {
a[0], a[i] = a[i], a[0]
} else {
a[c[i]], a[i] = a[i], a[c[i]]
}
fmt.Println(a)
c[i]++
i = 0
} else {
c[i] = 0
i++
}
}
}

func permch(a []int64, ch chan<- []int64) {
var n = len(a)
var c = make([]int, n)
ch <- a
i := 0
for i < n {
if c[i] < i {
if i%2 == 0 {
a[0], a[i] = a[i], a[0]
} else {
a[c[i]], a[i] = a[i], a[c[i]]
}
ch <- a
c[i]++
i = 0
} else {
c[i] = 0
i++
}
}
close(ch)
}

func main() {
var i = []int64{1, 2, 3}
fmt.Println("Without Channels")
perm(i)
ch := make(chan []int64)
go permch(i, ch)
fmt.Println("With Channels")
for slc := range ch {
fmt.Println(slc)
}

}

最佳答案

您的问题是 slice 是引用类型,并且在多个 goroutine 中被访问。在 perm 中,您在每一步完成处理后直接打印 a。在 permch 中,您正在通过 channel 发送 a,但随后立即开始再次修改它。由于通过 channel 发送的每个 slice 都引用相同的底层数组,因此您有一个竞争条件,即您的下一个循环迭代是否改变 a 或您在 main 中的 Println() 调用首先到达那个数组。

一般来说,如果您在任何使用 goroutines 的程序中遇到意外行为,您可能有竞争条件。使用 -race 标志运行程序以查看位置。

编辑:另外,关闭 channel 对从 channel 阅读的例行程序没有影响。可以继续读取 channel ,直到其缓冲区为空,此时它将开始返回该类型的零值。 channel 上的范围循环只会在 channel 关闭时终止并且其缓冲区为空

关于Golang range through channel 在实现堆排列算法时具有奇怪的行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43722558/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com