为什么通过通道发送的 Go 协程只打印一个值?

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

why go routine only prints one value when sent through channel

问题

我有以下代码:

import (
	"fmt"
)

func access(ch chan int) {
	for elem := range ch {
		fmt.Println(elem) // 只打印一个值
	}
	fmt.Println(<-ch) // 打印该值
	fmt.Println(<-ch) // 不打印

}
func main() {

	ch := make(chan int)

	go access(ch)
	ch <- 55 // 阻塞主程序
	ch <- 56 // 这个值永远不会打印

	fmt.Println("Hello, World!")
}

为什么只有通过通道发送的第一个值被打印出来,而不是其他的值,即使使用了无缓冲通道和for循环?

如果我使用for循环发送值,它就可以工作。

arr := []int{1, 1, 1, 1, 1}
for elem := range arr {
    ch <- elem
}

这里还有一个谜,如果我添加三个值发送到ch,所有的值都会在access函数中打印出来。这有点奇怪...

func access(ch chan int) {
    /*
    for elem := range ch {
        fmt.Println(elem)
    }
    */
    // 所有的打印
    fmt.Println(<-ch)
    fmt.Println(<-ch)
    fmt.Println(<-ch)
}

func main() {
    go access(ch)
    ch <- 55
    ch <- 56
    ch <- 57
}
英文:

I have following code

import (
	&quot;fmt&quot;
)

func access(ch chan int) {
	for elem := range ch {
		fmt.Println(elem) // prints only one as well
	}
	fmt.Println(&lt;-ch) // prints the value
	fmt.Println(&lt;-ch) // doesn&#39;t print

}
func main() {

	ch := make(chan int)

	go access(ch)
	ch &lt;- 55 // blocks the main routine
	ch &lt;- 56 // this value never prints

	fmt.Println(&quot;Hello, World!&quot;)
}

Why only the first value sent through channel gets printed not the other one ,even with for loop ,inspite of using unbuffered channel

If I use a for loop to send values it works

  arr:=[]int{1, 1, 1, 1, 1}
 for elem := range arr {
      ch&lt;-elem
    }

Here is another mystery ,if I add three values sending to ch.All values gets printed in the access function .this is bit strange .....................

 func access(ch chan int){
      /*
        for elem := range ch {
            fmt.Println(elem)
        }
        */
// All prints
      fmt.Println(&lt;-ch)
      fmt.Println(&lt;-ch)
        fmt.Println(&lt;-ch)
    
    }
    func main() {
    
  
    
    go access(ch)
     
    ch&lt;-55
    ch&lt;-56
    ch&lt;-57
    
    	
    }

答案1

得分: 1

发送第一个值后,main 协程被第二次发送操作阻塞,直到第一个值被处理,这就是为什么第一个数字会被打印出来,即使在主协程上没有等待的情况下。(我不确定这种行为是否由调度器保证,很可能不是。)但是在发送第二个值后,main 立即退出,没有给其他协程完成的机会。你可能想要先等待协程完成:

package main

import (
	"fmt"
	"sync"
)

func access(ch chan int) {
	fmt.Println(<-ch) // 打印值
	fmt.Println(<-ch) // 不打印
}

func main() {

	ch := make(chan int)

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		access(ch)
		wg.Done()
	}()
	ch <- 55
	ch <- 56
	wg.Wait()

	fmt.Println("Hello, World!")
}
英文:

After sending the first value, the main goroutine is blocked by the second send operation, until the first one is processed, that's why the first number is printed even without waiting on the main side. (I'm not sure that this behavior is guaranteed by the scheduler, most likely, not.) But after sending the second value, main exits immediately, without giving the other goroutine a chance to finish. You may want to wait for the goroutine to complete first:

package main

import (
	&quot;fmt&quot;
	&quot;sync&quot;
)

func access(ch chan int) {
	fmt.Println(&lt;-ch) // prints the value
	fmt.Println(&lt;-ch) // doesn&#39;t print
}

func main() {

	ch := make(chan int)

	var wg sync.WaitGroup
	wg.Add(1)
	go func() {
		access(ch)
		wg.Done()
	}()
	ch &lt;- 55
	ch &lt;- 56
	wg.Wait()

	fmt.Println(&quot;Hello, World!&quot;)
}

huangapple
  • 本文由 发表于 2022年1月3日 15:07:34
  • 转载请务必保留本文链接:https://go.coder-hub.com/70562586.html
匿名

发表评论

匿名网友

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

确定