为什么我的功能不归?

blz*_*blz 1 concurrency channel go goroutine

下面是一个启动外部进程的函数,将正则表达式与进程的标准输出进行匹配,并返回匹配的内容.

func (c *Colony) startCircuit(peer *string) (string, error) {
    var (
        err        error
        cmd        *exec.Cmd
        anchorChan chan string
    )

    // ... (omitted for readability)

    // get the anchor from standard output
    go func() {
        defer out.Close()

        anchorChan = make(chan string)
        for scanner := bufio.NewScanner(out); scanner.Scan(); {
            line := scanner.Text()
            if anchor := reRootAnchor.FindString(line); anchor != "" {
                log.Println("Started circuit server with anchor:", anchor)
                anchorChan <- anchor
                break
            }
        }
    }()

    anchor := <-anchorChan
    return anchor, err
}
Run Code Online (Sandbox Code Playgroud)

运行该函数时,我获得以下输出,表明确实找到了匹配并且(可能)被推入anchorChan:

2016/05/22 14:04:36 Started circuit server with anchor: circuit://[::]:36195/20666/Q431cc5fe613aa04b
Run Code Online (Sandbox Code Playgroud)

然而,startCircuit打电话似乎挂了.以下是相关的代码:

rootAnchor, err := c.startCircuit(peer)
if err != nil {
    return "", err
}
log.Fatal(rootAnchor) // DEBUG
Run Code Online (Sandbox Code Playgroud)

为什么startCircuit无限期地悬挂而不是返回?

T. *_*rie 5

问题其实很简单.提示:以下代码以死锁结束.

package main

import "fmt"

func main() {
    var c chan string

    go func() {
        c = make(chan string)
        c <- "42"
    }()

    str := <-c
    fmt.Println(str)
}
Run Code Online (Sandbox Code Playgroud)

从那里,问题是微不足道的.启动goroutine时,您的频道未初始化.有两个goroutines的比赛,显然去不能决定哪个应该优先考虑.

所以,你的答案是:make(chan ...)在goroutine开始之前调用,它应该解决你的问题.在有效的过程中有一个完美的例子.

  • 我不认为这是_quite_ right - 在goroutine比赛中使用`str:= <-c`语句在goroutine比赛中分配给`c`.因此赋值确实会影响main函数中的通道,并且代码不能保证死锁,但它肯定会被破坏,因为它包含一个种族.比赛探测器会抓住这个. (2认同)