【问题标题】:Executable exiting preemptively when ranging over an empty channel在空通道上测距时抢先退出的可执行文件
【发布时间】:2019-01-22 16:52:44
【问题描述】:

我最近遇到了一个我在 python 中解决的编码练习,我必须在其中移植一个“算法”。我不知道它是如何被调用的,这就是我描述它的原因: 每一个新行都是对前一行的描述,按顺序打印的相同数字的数量和相关的数字。 这是一个例子:

1
11
21
1211
111221
312211
etc

我开始学习 Go 的通道和并发特性。所以我回到了这个练习,试图与 Go 并行更有效地解决它。 这是我到目前为止得到的:

package main

func main() {
    channel := make(chan uint8)
    go treeCalcRoutine(channel, 0)
    channel <- 1
    close(channel) //defer is not an option in this case because the channel has 
    //to be closed before main exits
}

func treeCalcRoutine(in <-chan uint8, generation int) {
    if generation > 10 {
        return // return after 10 recursive iterations
    }
    out := make(chan uint8)
    defer close(out)
    num := uint8(1)
    previous := <-i
    go treeCalcRoutine(out, generation+1)
    for val := range in {
        switch {
        case val == previous:
            num++
        default:
            num = uint8(1)
            out <- num
            out <- val
        }
        previous = val
    }
    out <- num
    out <- previous
}

在尝试使用 Delve 调试程序时,我发现程序在尝试覆盖空/关闭的通道时无异常退出(并退出状态 0)。在这种情况下,我希望程序完全跳过 for 循环。 我仍然想自己解决这个挑战,所以如果有人能指出我正确的方向而不是产生一个有效的解决方案,我将不胜感激。此外,请指出任何其他可以做得更好的问题/案例(如generation 限制)。

编辑: 由于人们要求我发布错误:由于某种原因根本没有错误。程序一旦到达 for 循环就退出。

【问题讨论】:

  • 请发布实际错误和触发它的行。 “覆盖一个空的频道”没有错误 - 它只是等到有东西要接收。
  • 为什么close(channel) 作为main 中的最后一个语句可以做任何事情?我认为您对频道有一些根本性的误解。
  • @JimB 据我所知,for range 循环永远不会停止循环,除非通道关闭。
  • @Swiftb0y 不,不是这样。关闭通道将关闭通道,如果通道关闭,您将无法在通道上发送更多值,编译器将抛出错误提示无法在关闭的通道上发送值。
  • @Swiftb0y: 关闭通道会导致 for range 循环退出,但在main 结束时程序正在退出,所以这并不重要。

标签: go concurrency range channel


【解决方案1】:

所以问题实际上并不是 for 循环在遇到关闭的通道时退出,而是主例程在那个确切的时间退出,这导致所有其他 goroutine 也终止。我被建议在这种情况下使用等待组。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多