两个 goroutine:go1,go2
go1 从 socket 读,读到的数据写到 ch1
go2 从 ch2 读,读到的数据写到 socket
以此来实现全双工通信
问题:ch1 关闭之后,go1 不知道,一写就崩了,怎么避免?
1 shakeyo 2021-04-27 16:35:39 +08:00 创建一个用于通知的 chan for 循环里监听这个 chan 是否有消息 在关闭的时候写入 在读取的时候监听 有信号退出当前 channel 就行 |
2 bfdh 2021-04-27 16:40:34 +08:00 ![]() 溴 ( xiù ) (英:Bromine )是一化元素,其化符为 Br,原子序为 35 摘自维基百科 |
![]() | 3 hwdef 2021-04-27 16:41:31 +08:00 从 ch 读的时候,可以检查是否已关闭了。 |
4 brader 2021-04-27 16:43:28 +08:00 这确实是个问题,需要今晚好好研究下 |
![]() | 5 masterclock 2021-04-27 16:47:10 +08:00 ![]() chan 仅由写的一方关闭 |
![]() | 6 bruce00 2021-04-27 16:48:32 +08:00 [How to Gracefully Close Channels]( https://go101.org/article/channel-closing.html) ```go func SafeSend(ch chan T, value T) (closed bool) { defer func() { if recover() != nil { closed = true } }() ch <- value // panic if ch is closed return false // <=> closed= false; return } ``` |
![]() | 7 keepeye 2021-04-27 16:48:53 +08:00 ![]() ch1 由 go1 关闭,也就是永远由写的一方关闭 channel |
8 PinkPumpkin 2021-04-27 16:49:50 +08:00 via Android ![]() 糗 qiǔ,溴 xiù |
![]() | 9 juzisang 2021-04-27 16:52:23 +08:00 ![]() 秀大了 |
![]() | 10 linvon 2021-04-27 16:53:06 +08:00 go1 来关闭啊,怎么可能由消费者去关闭通道 go2 用 for range 去读,也能感知到关闭 |
![]() | 11 echo1937 2021-04-27 16:54:10 +08:00 ![]() 你打标题的时候,又糗大了了一次。 |
![]() | 12 Latin 2021-04-27 16:58:14 +08:00 我怀疑你是套娃 给自己问问题 |
13 name1991 2021-04-27 17:13:56 +08:00 女同事很会发现问题 |
![]() | 14 Presbyter 2021-04-27 17:16:52 +08:00 可以考虑用 context Cancel 控制一下 go1(ctx){ ... select{ case <-ctx.Done(): return ...... } ..... } |
![]() | 15 SmartKeyerror 2021-04-27 17:19:21 +08:00 The close built-in function closes a channel, which must be either bidirectional or send-only. It should be executed only by the sender, never the receiver, and has the effect of shutting down the channel after the last sent value is received. https://pkg.go.dev/builtin#close |
![]() | 16 yogogo 2021-04-27 17:19:25 +08:00 娶回家 |
![]() | 17 lasuar 2021-04-27 17:22:56 +08:00 5 楼就是答案 |
18 zhaohua 2021-04-27 17:49:14 +08:00 如果把问题简化为: 从关闭的 ch 中读取数据,如何才能不崩溃,答案是:做不到. |
19 2kCS5c0b0ITXE5k2 2021-04-27 18:05:35 +08:00 ![]() 你又可以发一贴 在 V2EX 发帖 认错字了 糗大了 |
![]() | 20 Vegetable 2021-04-28 09:54:35 +08:00 没人提但是我很好奇,panic 了就 recover 一下不也算方案吗 |
![]() | 21 yefuchao 2021-04-28 14:50:42 +08:00 https://tour.golang.org/concurrency/4 A sender can close a channel to indicate that no more values will be sent. Receivers can test whether a channel has been closed by assigning a second parameter to the receive expression |
![]() | 22 rekulas 2021-04-30 13:13:56 +08:00 用指针应该有办法判断,但并不是好办法,最好还是听楼上的意见自己处理关闭 |
![]() | 23 iceteacover 2021-05-14 14:23:57 +08:00 我是来抖机灵的: 不要把问技术问题女性当成女性。 不抖机灵的: 技术面前人人平等,请先尊重你同事的专业能力,再尊重性别。 |
![]() | 24 Lihanx9 2021-06-08 10:51:06 +08:00 如果是针对这个场景,不要求必须使用 channel 的话。goroutine 里用 io.Copy 读写,根据返回值或者异常判断结束退出 goroutine,另外 io.Copy 用在 net.Conn 上的时候,底层会调用 sendfile,零拷贝效率可能还会高一点。这是我最近遇到这个问题用的方法,不知道对不对啊... |
![]() | 25 cyrivlclth 2021-06-24 11:06:09 +08:00 @zhaohua 读取被关的 channel 不会崩。。。写才会 |