猿问

为什么我的函数没有返回?

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


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

}

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


2016/05/22 14:04:36 Started circuit server with anchor: circuit://[::]:36195/20666/Q431cc5fe613aa04b

但是,startCircuit来电者似乎挂起。这是相关的代码:


rootAnchor, err := c.startCircuit(peer)

if err != nil {

    return "", err

}

log.Fatal(rootAnchor) // DEBUG

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


天涯尽头无女友
浏览 207回答 2
2回答

慕的地10843

这个问题其实很简单。提示:以下代码以deadlock结尾。package mainimport "fmt"func main() {&nbsp; &nbsp; var c chan string&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; c = make(chan string)&nbsp; &nbsp; &nbsp; &nbsp; c <- "42"&nbsp; &nbsp; }()&nbsp; &nbsp; str := <-c&nbsp; &nbsp; fmt.Println(str)}从那里,问题是微不足道的。当您启动 goroutine 时,您的频道未初始化。两个 goroutine 之间存在竞争,显然 go 无法决定哪个应该具有优先级。所以,你的答案是:make(chan ...)在 goroutine 开始之前调用,它应该可以解决你的问题。在有效围棋中有一个完美的例子。

qq_花开花谢_0

Dave Cheney 有一篇很好的相关博文:http&nbsp;:&nbsp;//dave.cheney.net/2014/03/19/channel-axioms最相关的点:发送到 nil 通道永远阻塞来自 nil 通道的接收永远阻塞由于未初始化的通道为零,因此对其进行任何读写都会导致死锁。例如,在 T. Claverie 的回答中,有一场比赛:如果c = make(chan string), (并且c <- "42"我相信此时str := <-c必须等待)首先发生,然后从初始化的非空通道接收,一切运行正常:package mainimport "fmt"import "time"func main() {&nbsp; &nbsp; var c chan string&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; c = make(chan string)&nbsp; &nbsp; &nbsp; &nbsp; c <- "42"&nbsp; &nbsp; }()&nbsp; &nbsp; time.Sleep(time.Second * 1)&nbsp; &nbsp; str := <-c&nbsp; &nbsp; fmt.Println(str)}你可以运行上面的例子来说服自己。(这不是好的做法,甚至不能保证每次都有效。)但是,如果str := <-c先发生,那么您正在从一个nil通道接收,这会导致死锁。
随时随地看视频慕课网APP

相关分类

Go
我要回答