go检查channel是否关闭
golang 中channel 即使已经关闭了, 仍然可以将channel中的数据读出来, 并不会报错。
一般的写法: data, ok := <- chan,
只有当channel无数据,且channel被close了,才会返回ok=false。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 | package main import ( "context" "fmt" "reflect" "time" "unsafe" ) func isChanClosed(ch interface {}) bool { if reflect.TypeOf(ch).Kind() != reflect.Chan { panic( "only channels!" ) } // get interface value pointer, from cgo_export // typedef struct { void *t; void *v; } GoInterface; // then get channel real pointer cptr := *(*uintptr)(unsafe.Pointer( unsafe.Pointer(uintptr(unsafe.Pointer(&ch)) + unsafe.Sizeof(uint(0))), )) // this function will return true if chan.closed > 0 // see hchan on https://github.com/golang/go/blob/master/src/runtime/chan.go // type hchan struct { // qcount uint // total data in the queue // dataqsiz uint // size of the circular queue // buf unsafe.Pointer // points to an array of dataqsiz elements // elemsize uint16 // closed uint32 // ** cptr += unsafe.Sizeof(uint(0)) * 2 cptr += unsafe.Sizeof(unsafe.Pointer(uintptr(0))) cptr += unsafe.Sizeof(uint16(0)) return *(*uint32)(unsafe.Pointer(cptr)) > 0 } func main() { c := make( chan int, 10) c <- 1 c <- 2 c <- 3 ctx, cancel := context.WithCancel(context.Background()) close(c) cancel() fmt.Println( "whether channel is closed:" , isChanClosed(c), "\n" ) exit: for { select { case i, ok := <-c: fmt.Println(ok) if !ok { fmt.Println( "channel closed!" ) break } fmt.Println(i) case <-ctx.Done(): break exit } } fmt.Println( "aaaaaaaa" ) time.Sleep(time.Second * 2) } |
我们都知道data, ok := <- chan第一个变量表示读出的数据,第二个变量表示是否成功读取了数据,有意思的是,第二个变量并不用于指示管道的关闭的状态。第二个变量常常被误以为关闭状态是因为它确实和管道状态有关,确切的来说,是和管道缓冲区是否有数据有关。
如果判断golang的channel是否关闭,data, ok := <- chan,当ok不是true的时候,说明是channel关闭了。 那么问题来了,channel关闭了,我们是否可以立马获取到channel被关闭的状态?我想这个问题不少人没有去想吧?为什么有这样的问题? 来自我的一个bug,我期初认为close了一个channel,消费端的goroutine自然是可以拿到channel的关闭状态。然而事实并不是这样的。 只有当channel无数据,且channel被close了,才会返回ok=false。 所以,只要有堆积,就不会返回关闭状态。导致我的服务花时间来消费堆积,才会退出。
————————————————
版权声明:本文为CSDN博主「github_zwl」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/github_34457546/article/details/109687879
参考: https://blog.csdn.net/github_34457546/article/details/109687879
----------------------------------------------
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 25岁的心里话
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
2017-05-12 gcc 与 g++的区别
2016-05-12 php 内置的 webserver 研究。
2016-05-12 php 系列