猿问

如何在同一循环内向/从通道发送和接收值?

下面是一个例子:


func main() {

    c := make(chan int)

    i := 0


    go goroutine(c)


    c <- i

    time.Sleep(10 * time.Second)


}


func goroutine(c chan int) {

    for {

        num := <- c

        fmt.Println(num)

        num++

        time.Sleep(1 * time.Second)

        c <- num

    }

}

我在 goroutine 中尝试做的是从通道接收数字,打印它,递增并在一秒钟后将其发送回通道。在此之后,我想重复这个动作。


但因此,操作只进行一次。


输出:


0

难道我做错了什么?


MM们
浏览 159回答 3
3回答

MMTTMM

默认情况下,goroutine 通信是synchronousand unbuffered: 发送不会完成,直到有接收者接受该值。必须有一个接收者准备好从通道接收数据,然后发送者可以将它直接交给接收者。所以通道发送/接收操作阻塞,直到另一端准备好:1.通道上的发送操作会阻塞,直到接收器可用于同一通道:如果没有接收器的值 on ch,则不能将其他值放入通道。反之亦然:ch当通道不为空时,不能发送新值!因此发送操作将等待直到ch再次可用。2.通道的接收操作阻塞,直到发送方可用于同一通道:如果通道中没有值,则接收方阻塞。下面的示例说明了这一点:package mainimport "fmt"func main() {&nbsp; &nbsp; ch1 := make(chan int)&nbsp; &nbsp; go pump(ch1) // pump hangs&nbsp; &nbsp; fmt.Println(<-ch1) // prints only 0}func pump(ch chan int) {&nbsp; &nbsp; for i:= 0; ; i++ {&nbsp; &nbsp; &nbsp; &nbsp; ch <- i&nbsp; &nbsp; }}因为没有接收器,goroutine 挂起并只打印第一个数字。为了解决这个问题,我们需要定义一个新的 goroutine,它以无限循环的方式从通道中读取数据。func receive(ch chan int) {&nbsp; &nbsp; for {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(<- ch)&nbsp; &nbsp; }}然后在main():func main() {&nbsp; &nbsp; ch := make(chan int)&nbsp; &nbsp; go pump(ch)&nbsp; &nbsp; go receive(ch)}Go Playground

桃花长相依

您创建一个无缓冲通道c与c&nbsp;:=&nbsp;make(chan&nbsp;int)在无缓冲通道上,操作是对称的,即通道上的每次发送都需要一次接收,每次接收都需要一次发送。您将您的发送i到频道,goroutine 将其接收到num.&nbsp;之后,goroutine 将增量发送num到通道中,但没有人在那里接收它。简而言之:声明c&nbsp;<-&nbsp;num会阻塞。您可以使用 1 缓冲通道,这应该可以工作。您通过等待 10 秒解决了您的代码的另一个问题main:您不知道 goroutine 何时完成。通常,sync.WaitGroup在这些情况下使用a&nbsp;。但是:你的 goroutine 没有完成。chan struct{}一段时间后在主协程中并select通过工作协程中的两个通道引入一个是惯用的。

慕田峪7331174

你使用无缓冲通道,所以你的 goroutine 挂起c <- num你应该使用缓冲通道,像这样:c := make(chan int, 1)试试吧&nbsp;Go playground
随时随地看视频慕课网APP

相关分类

Go
我要回答