为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
天涯尽头无女友 2022-01-10 18:47:52
下面是一个函数,它启动一个外部进程,将正则表达式与进程的标准输出进行匹配,并返回匹配的内容。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无限期挂起而不是返回?
查看完整描述

2 回答

?
慕的地10843

TA贡献1785条经验 获得超8个赞

这个问题其实很简单。提示:以下代码以deadlock结尾。


package main


import "fmt"


func main() {

    var c chan string


    go func() {

        c = make(chan string)

        c <- "42"

    }()


    str := <-c

    fmt.Println(str)

}

从那里,问题是微不足道的。当您启动 goroutine 时,您的频道未初始化。两个 goroutine 之间存在竞争,显然 go 无法决定哪个应该具有优先级。


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


查看完整回答
反对 回复 2022-01-10
?
qq_花开花谢_0

TA贡献1835条经验 获得超7个赞

Dave Cheney 有一篇很好的相关博文:http : //dave.cheney.net/2014/03/19/channel-axioms

最相关的点:

  1. 发送到 nil 通道永远阻塞

  2. 来自 nil 通道的接收永远阻塞

由于未初始化的通道为零,因此对其进行任何读写都会导致死锁。例如,在 T. Claverie 的回答中,有一场比赛:如果c = make(chan string), (并且c <- "42"我相信此时str := <-c必须等待)首先发生,然后从初始化的非空通道接收,一切运行正常:

package main


import "fmt"

import "time"


func main() {

    var c chan string


    go func() {

        c = make(chan string)

        c <- "42"

    }()


    time.Sleep(time.Second * 1)

    str := <-c

    fmt.Println(str)

}


你可以运行上面的例子来说服自己。(这不是好的做法,甚至不能保证每次都有效。)


但是,如果str := <-c先发生,那么您正在从一个nil通道接收,这会导致死锁。


查看完整回答
反对 回复 2022-01-10
  • 2 回答
  • 0 关注
  • 204 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号