go - 如何在同一循环内向 channel 发送值或从 channel 接收值?

标签 go channel goroutine

这是一个例子:

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 内部做的是从 channel 接收数字,打印它,递增并在一秒钟后将它发送回 channel 。在此之后我想重复这个 Action 。

但结果,操作只做了一次。

输出:

0

我做错了什么吗?

最佳答案

默认情况下,goroutine 通信是同步无缓冲:在接收方接受值之前发送不会完成。必须有一个接收方准备好从 channel 接收数据,然后发送方可以将数据直接交给接收方。

所以 channel 发送/接收操作阻塞,直到另一端准备好:

1. channel 上的发送操作会阻塞,直到接收方可用于同一 channel :如果 ch 上的值没有接收方,则没有其他值可以放在 channel 里。反之亦然:当 channel 不为空时,不能在 ch 中发送新值!因此发送操作将等到 ch 再次可用。

2. channel 的接收操作阻塞,直到发送方可用于同一 channel :如果 channel 中没有值,则接收方阻塞。

下面的例子说明了这一点:

package main
import "fmt"

func main() {
    ch1 := make(chan int)
    go pump(ch1) // pump hangs
    fmt.Println(<-ch1) // prints only 0
}

func pump(ch chan int) {
    for i:= 0; ; i++ {
        ch <- i
    }
}

因为没有接收者,goroutine 挂起并只打印第一个数字。

为了解决这个问题,我们需要定义一个新的 goroutine,它在无限循环中从 channel 中读取数据。

func receive(ch chan int) {
    for {
        fmt.Println(<- ch)
    }
}

然后在 main() 中:

func main() {
    ch := make(chan int)
    go pump(ch)
    go receive(ch)
}

Go Playground

关于go - 如何在同一循环内向 channel 发送值或从 channel 接收值?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34760364/

相关文章:

go - 限制运行的例程数量

function - 函数可以作为参数传递吗?

go - 列出按条件过滤的 Firestore 集合 ID

go - 共享内存与 Go channel 通信

java - HttpPost : InputDispatcher: "Channel is unrecoverably broken and will be disposed!" on Nexus 7

java - Java中如何异步调用方法

go - 每 N 秒运行一次函数,上下文超时

go - 在Go项目中访问静态文件

go - 将大型结构的 const 指针传递给函数或 go channel

go - 我在 golang 中错误地使用了 channel 吗?