【问题标题】:Go: fatal error: all goroutines are asleep - deadlockGo:致命错误:所有 goroutines 都处于睡眠状态 - 死锁
【发布时间】:2016-07-30 00:52:49
【问题描述】:

我有一个文本文件,里面只有一行字。我想将所有这些单词分别存储在一个频道中,然后从频道中将它们全部提取出来并一一打印出来。我有以下代码:

func main() {
    f, _ := os.Open("D:\\input1.txt")
    scanner := bufio.NewScanner(f)
    file1chan := make(chan string)   
    for scanner.Scan() {
        line := scanner.Text()

        // Split the line on a space
        parts := strings.Fields(line)

        for i := range parts {   
            file1chan <- parts[i]
        }    
    }
    print(file1chan)
}

func print(in <-chan string) {
    for str := range in {
        fmt.Printf("%s\n", str)
    }
}

但是当我运行它时,我得到以下错误:

致命错误:所有 goroutine 都处于休眠状态 - 死锁!

goroutine 1 [chan send]: main.main()

我尝试在网上查找它,但我仍然无法修复它。谁能告诉我为什么会发生这种情况以及我该如何解决它?

谢谢!

【问题讨论】:

    标签: go deadlock


    【解决方案1】:

    您的file1chan 没有缓冲,因此当您尝试通过该通道发送值时,它会永远阻塞,等待有人获取值。

    您需要启动一个新的 goroutine,或者将通道缓冲并将其用作数组。这是带有另一个 goroutine 的版本:

    func main() {
        f, _ := os.Open("D:\\input1.txt")
        scanner := bufio.NewScanner(f)
        file1chan := make(chan string)
        go func() { // start a new goroutine that sends strings down file1chan 
            for scanner.Scan() {
                line := scanner.Text()
    
                // Split the line on a space
                parts := strings.Fields(line)
    
                for i := range parts {
                    file1chan <- parts[i]
                }
            }
            close(file1chan)
        }()
        print(file1chan) // read strings from file1chan
    }
    
    func print(in <-chan string) {
        for str := range in {
            fmt.Printf("%s\n", str)
        }
    }
    

    这是缓冲版本,仅用于处理单个字符串:

    func main() {
        f, _ := os.Open("D:\\input1.txt")
        scanner := bufio.NewScanner(f)
        file1chan := make(chan string, 1) // buffer size of one
        for scanner.Scan() {
            line := scanner.Text()
    
            // Split the line on a space
            parts := strings.Fields(line)
    
            for i := range parts {
                file1chan <- parts[i]
            }
        }
        close(file1chan) // we're done sending to this channel now, so we close it.
        print(file1chan)
    }
    
    func print(in <-chan string) {
        for str := range in { // read all values until channel gets closed
            fmt.Printf("%s\n", str)
        }
    }
    

    【讨论】:

    • 我不能让它缓冲,因为我“大概”不知道文件中有多少字,那我还能做什么?使用一个 goroutine 将值存储在文件中,并使用另一个 goroutine 打印它们?
    • 没错。如果你可以确定你从扫描器中得到的字符串不会超过n,你可以使用大小为n的缓冲通道。我添加了两个版本。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-04-22
    • 1970-01-01
    • 2015-01-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多