Go: 致命错误:所有的goroutine都处于休眠状态 – 死锁

huangapple go评论75阅读模式
英文:

Go: fatal error: all goroutines are asleep - deadlock

问题

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

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)
    }
}

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

fatal error: all goroutines are asleep - deadlock!

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

我尝试在网上查找,但仍然无法解决它。请问有人可以告诉我为什么会发生这种情况,以及如何解决它吗?

谢谢!

英文:

I have a text file with just one line of words in it. I want to store all of those words separately in a channel, and then extract them all from the channel and print them one by one. I have the following code:

func main() {
	f, _ := os.Open(&quot;D:\\input1.txt&quot;)
	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 &lt;- parts[i]
		}    
	}
	print(file1chan)
}

func print(in &lt;-chan string) {
	for str := range in {
		fmt.Printf(&quot;%s\n&quot;, str)
	}
}

But when i run it i get the following error:

> fatal error: all goroutines are asleep - deadlock!
>
> goroutine 1 [chan send]: main.main()

I tried looking it up online but i still couldn't manage to fix it. Could anybody please tell me why this is happening and how i can go about fixing it?

Thanks!

答案1

得分: 7

你的file1chan是无缓冲的,所以当你尝试向该通道发送一个值时,它会永远阻塞,等待有人获取一个值。

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

func main() {
    f, _ := os.Open("D:\\input1.txt")
    scanner := bufio.NewScanner(f)
    file1chan := make(chan string)
    go func() { // 启动一个新的goroutine,将字符串发送到file1chan
        for scanner.Scan() {
            line := scanner.Text()

            // 在空格上分割行
            parts := strings.Fields(line)

            for i := range parts {
                file1chan <- parts[i]
            }
        }
        close(file1chan)
    }()
    print(file1chan) // 从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) // 缓冲区大小为1
    for scanner.Scan() {
        line := scanner.Text()

        // 在空格上分割行
        parts := strings.Fields(line)

        for i := range parts {
            file1chan <- parts[i]
        }
    }
    close(file1chan) // 我们现在发送到该通道的操作已完成,所以关闭它。
    print(file1chan)
}

func print(in <-chan string) {
    for str := range in { // 读取直到通道关闭的所有值
        fmt.Printf("%s\n", str)
    }
}
英文:

Your file1chan is unbuffered, so when you try to send a value down that channel, it blocks forever, waiting for someone to fetch a value.

You need to start a new goroutine, or make the channel buffered and use it as an array. Here's the version with another goroutine:

func main() {
	f, _ := os.Open(&quot;D:\\input1.txt&quot;)
	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 &lt;- parts[i]
			}
		}
		close(file1chan)
	}()
	print(file1chan) // read strings from file1chan
}

func print(in &lt;-chan string) {
	for str := range in {
		fmt.Printf(&quot;%s\n&quot;, str)
	}
}

And here's the buffered version, for handling only a single string:

func main() {
	f, _ := os.Open(&quot;D:\\input1.txt&quot;)
	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 &lt;- parts[i]
		}
	}
	close(file1chan) // we&#39;re done sending to this channel now, so we close it.
	print(file1chan)
}

func print(in &lt;-chan string) {
	for str := range in { // read all values until channel gets closed
		fmt.Printf(&quot;%s\n&quot;, str)
	}
}

huangapple
  • 本文由 发表于 2016年4月9日 00:44:33
  • 转载请务必保留本文链接:https://go.coder-hub.com/36505012.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定