关于channel的一些问题
来源:13-8 双向和单向的channel

JxinBain
2021-05-31
package main
import (
"fmt"
"sync"
"time"
)
var wg sync.WaitGroup
func comsumer(queue chan int) {
defer wg.Done()
for {
data, ok := <-queue
if !ok {
break
}
fmt.Println(data, ok)
time.Sleep(time.Second)
/*
把添加数据到channel的语句挪到for循环之内,程序正常运行
*/
//queue <- 20
//fmt.Println("添加数据成功")
}
fmt.Println("循环结束")
/*
把添加数据到channel的语句挪到for循环之外,则会报错
*/
queue <- 20
fmt.Println("添加数据成功")
}
func main() {
/*
channel 类型分类的两个维度
有缓冲的还是无缓冲的
单项的还是双向的
*/
// 定义一个channel
var msgs chan int
msgs = make(chan int) // 第一种初始化方式:无缓冲 先启动消费者 再放数据 就不会panic
wg.Add(1)
go comsumer(msgs)
msgs <- 1
fmt.Println("等待返回值")
// 这里从管道取值是会阻塞 如果注释掉这行代码 那么管道会直接关闭 导致 comsumer方法里面给管道里添加值的语句报错
data := <-msgs
fmt.Println(data)
close(msgs)
//fmt.Println("channel已关闭")
wg.Wait()
}
老师你好 我想请问一下 关于我comsumer方法里面 我把添加数据到channel的语句(queue <- 20)挪到for循环体外面的时候,程序会报错 以下是错误信息
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
D:/LessonProject/Go-Python微服务/GoProject/GoLang/c13/channel_type/main.go:48 +0x128
goroutine 6 [chan receive]:
main.comsumer(0xc00004a060)
D:/LessonProject/Go-Python微服务/GoProject/GoLang/c13/channel_type/main.go:14 +0x137
created by main.main
D:/LessonProject/Go-Python微服务/GoProject/GoLang/c13/channel_type/main.go:44 +0x8a
但是如果我把 queue <- 20 放到循环体内的时候 程序则不会报错 程序正常运行 这是为什么呢?
写回答
1回答
-
bobby
2021-06-01
首先这个问题非常棒,也是非常好的案例,这是一个典型的go的无缓冲channel的细节问题,实际开发过程中很容易面临,而且面试过程中也很容易遇到,其实一句话总结就是:
无缓冲channel容易踩坑, 先说一句结论:无缓冲的channel发送的时候需要有地方应开始等着接收了。反过来也是一样的,你上面把发送放到外面,https://zhuanlan.zhihu.com/p/101063277 你可以先看看这篇好好了解一下无缓冲channel
022021-06-04
相似问题