buffered channel的设计简直匪夷所思,什么“内存有限,无限长的队列不符合逻辑”的鬼话。简直是bullshit,逻辑上的queue就可以是无限大的,就像slice和map是“无限大”的一样。
举例来说,当你需要多线程bfs的时候,一个无限大的queue就是必须的,因为程序无法预估图的规模。那么问题来了,如何在golang中实现一个无限大的、线程安全的、有Timeout的queue呢?我发现在Golang中实现一个有Timeout的queue特别麻烦,只能用很不优雅的workaround。主要原因在于Golang的sync.Cond竟然不支持类似pthread的pthread_cond_timedwait的方法。
现在的workaround是一个双链表+两个channel+两个routine处理输入输出,在外部用select+ticker,才勉强实现了这个功能。在此想请教下有什么优雅的方法实现一个类似Python中queue.Queue的数据结构。
PS. 我真是服了,回复全是给Golang洗地的,说辞全是“需要无限长的Queue就是你程序有问题”,而没有一个回答问题的。
PPS. 大概实现了一个支持Timeout的Condition variable,但是非常简陋,并不能支持notify_all.
type myCond struct { l *sync.Mutex ch chan bool } func (c *myCond) waitTimeout(timeout time.Duration) error { c.l.Unlock() defer c.l.Lock() select { case <-time.After(timeout): return fmt.Errorf("wait timeout") case <-c.ch: return nil } } func (c *myCond) wait() { c.l.Unlock() defer c.l.Lock() <-c.ch } func (c *myCond) notify() { select { case c.ch <- true: return default: return } }
wanghaohebe (诗者之殇), 信区: Golang
标 题: Re: 【问题】golang中如何实现一个无限长的Queue
发信站: 北邮人论坛 (Thu May 16 15:52:23 2019), 站内
无限大的queue要有Timeout干嘛?内存有限,无限长的队列又有什么意义,给你实现了无界channel,你真能装无限的数据?有界channel才会让你思考该怎么设计使用,而不是无脑往队列里面塞东西直到内存爆掉。如果真要装超出内存的数据,就不应该再用简单的channel了
我真是服了您这种Golang maniac/cultist。逻辑上的无穷和实际的无限大是一回事吗?您按照的您的思路回答一下,为什么slice可以不用限定最大容量?你要无脑往Slice里装超过内存的数据?有些情况根本没法预估问题的规模,比如BFS,这个时候当然需要一个逻辑上“无限大”的queue。
换个问法问您,Python的queue.Queue、Java的BlockingQueue都是没意义的?这些设计都是为了让人撑爆内存的?
Golang大概是诞生于21世纪的语言中,技术品味最差的一个,还有一堆cultists无脑洗地,简直了……
ython的queue.Queue、Java的BlockingQueue都不是语言层面的东西吧?你要是觉得这种无限大的队列有必要你可以自己写了往golang的标准库里面提交啊?你觉得你比golang的设计者还牛逼?逻辑上的无穷和实际的无限大不是一回事,就是要在设计上就不让没水平的代码导致实际的无限大。通过通信共享内存,不是让你用通信来撑爆内存的。你可以不喜欢golang的设计思想,但是你没法否定它在各种设计上简单和鲁棒。就跟map遍历一样,就是要加随机种子使它无序。我不搞golang开发,所谓的cultist也就呵呵了。既然你这么讨厌golang,干嘛还要用它研究它
刚开始学go还不了解,原来buffered channel是这个意思……那实际上是需要一个不阻塞写入、动态扩容的channel吧。我这么菜也不知道底层怎么实现的,能不能检测到满了就重新申请两倍拷过去并且不触发通知等待者
您问问自己,没有无限大的Queue怎么BFS。先DFS一次计算规模?那你不还是需要一个无限的stack?
最简单的场景,我给你一颗二叉树的根节点,树的规模未知,你来用channel层序遍历一下试试。
Golang用户都不学数据结构的嘛……
我感觉不只是Golang,Google的信徒好多疯子,说不得Google的不好,微软三个月就要倒闭,殊不知Google把自己牌坊都快卖了
Golang社区充斥着你这么用是你2b,我们不需要这种feature,写了快十年interface{},还不是要在2.0把泛型加回来
带waitfor的condition variable我不得不自己实现了一个,垃圾标准库啊
回到题主的问题,无限长的queue我用了一个第三方库,可自动扩容的环形queue,实现思想跟其他语言差不多