go - go中如何使用通道?
问题描述
我有一个函数,它接受一个 int 数组并将它们转储到一个通道中。
func Dump(a []int, ch chan int) {
for i := range a {
ch <- i
}
close(ch)
}
这个主要不建立:
func main() {
ch := make(chan int)
arr := []int{1, 2, 3, 4, 5}
Dump(arr, ch)
for i := range ch {
fmt.Printf("Got %v\n", i)
}
}
抛出此错误:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan send]:
main.Dump(0xc000078f48, 0x5, 0x5, 0xc00006e060)
/Users/300041738/go-workspace/src/test.go:7 +0x43
main.main()
/Users/300041738/go-workspace/src/test.go:15 +0x9b
exit status 2
但是,这会构建:
func main() {
ch := make(chan int)
arr := []int{1, 2, 3, 4, 5}
go Dump(arr, ch)
for i := range ch {
fmt.Printf("Got %v\n", i)
}
}
为什么我必须在 Dump 前面写 go?我不希望异步转储数组的内容。
解决方案
通道有缓冲区。默认情况下,缓冲区的大小为 0。换句话说,如果要将元素插入到非缓冲通道中,插入的 goroutine 将停止,直到另一个 goroutine 从通道中检索值。
所以为了好玩,试试这个:
import "fmt"
func Dump(a []int, ch chan int) {
for i := range a {
ch <- i
}
close(ch)
}
func main() {
arr := []int{1, 2, 3, 4, 5}
ch := make(chan int, len(arr)) //specify channel buffer length equal to arr size
Dump(arr, ch)
for {
i, ok := <- ch
if ok {
fmt.Println("received a number !", i)
} else {
fmt.Println("channel is closed, we're done here")
}
}
}
推荐阅读
- c# - SqlException 而 Linq to Sql
- influxdb - 如何返回 N 个最“重”的请求
- javascript - 尝试读取元素的文本仅显示第一个元素的文本
- r - DT::datatables() 生成的 html 表在使用列级搜索时显示显示异常(缺少字符)
- python - 如何将本地 API 与在不同端口提供的 Vue 应用程序一起使用?
- excel - 使用 Excel VBA 根据常用单元格值向多人发送电子邮件
- pandas - 如何重新采样(上采样)我的 Pandas 数据框?
- python - 将两个数组合并为一个数组,插入一个函数
- r - 如何按组计算平均值并替换R数据框中的日期
- android - 从 Kotlin 中的泛型获取类