Selecting from an array of channels?

blov · · 495 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I have recently started learning go, and for a project I&#39;m building I was wondering if there&#39;s a clean way of selecting from an array of channels for example like below</p> <pre><code> func boss(worker_chans[n]chan byte) { for { select { case y := &lt;- worker_chans[i int]: read_in &lt;- worker_chans[i] break } } } </code></pre> <p>Notice how the select statement is able to distinguish which channel in the array is being communicated with and ties that to a bound variable i. In other concurrent languages I&#39;ve learnt <a href="https://en.wikipedia.org/wiki/XC_%28programming_language%29#Communication" rel="nofollow">xC</a> , this has been possible. Do I have to explicitly give each channel a select, thereby copying and pasting code, or is this possible in some way?</p> <hr/>**评论:**<br/><br/>tv64738: <pre><p>Make the workers send their results on a single channel.</p></pre>Keplerspace: <pre><p>I agree with this answer. There shouldn&#39;t be a need to select from an array of channels. I think that sometimes people try and make a language like another one, but idiomatic Go code is often what works best in my experience.</p></pre>the_omicron: <pre><p>I agree, I would make it a struct channel with sender or worker ID embedded in.</p></pre>epiris: <pre><p>In practice you won&#39;t need to do this, as mentioned by tv64738 you should fan in the results to a single channel. Your question is covered very well in <a href="https://blog.golang.org/pipelines" rel="nofollow">blog.golang.org - Go Concurrency Patterns: Pipelines and cancellation</a>.</p></pre>dilap: <pre><p>Surprisingly, there is no built-in syntax to do this.</p> <p>You can do it using the reflect package, however, with the function reflect.Select.</p> <p>It&#39;s a little unwieldy, but it works: <a href="https://play.golang.org/p/wCchjGndBC" rel="nofollow">https://play.golang.org/p/wCchjGndBC</a></p></pre>AsexyFootballFan: <pre><p>Does there happen to be a reason this syntax is not built in? </p></pre>dilap: <pre><p>I found this post by Russ Cox (a very early and influential go team member): </p> <blockquote> <p>We intentionally left array select out. It&#39;s an expensive operation and can often be avoided by arranging for the various senders to send on a shared channel instead.</p> </blockquote> <p>(<a href="https://groups.google.com/d/msg/golang-nuts/ZXDfIkVk54g/BcrR50rVrdsJ" rel="nofollow">https://groups.google.com/d/msg/golang-nuts/ZXDfIkVk54g/BcrR50rVrdsJ</a>)</p> <p>So in your example, rather than channel per worker, just one channel that all workers send too. If you need to know which worker you got a message from, have them include that info in the message they&#39;re sending on the channel.</p></pre>stymiedcoder: <pre><p>Check out the reflect package. Specifically <a href="https://golang.org/pkg/reflect/#Select" rel="nofollow">https://golang.org/pkg/reflect/#Select</a></p></pre>brokedown: <pre><p>Please consider not doing this.</p></pre>itsamemmario: <pre><p>I agree with the other answers that you should simply make all workers send to a single channel. But if for some reason you still want an array of channels you could do something like this.</p> <p><a href="https://play.golang.org/p/Ev-kY0ve1G" rel="nofollow">https://play.golang.org/p/Ev-kY0ve1G</a></p> <p>It&#39;s a fun exercise but not that useful :P</p></pre>connor4312: <pre><p>reflect.Select is what you&#39;re after. Example here: <a href="https://stackoverflow.com/questions/19992334/how-to-listen-to-n-channels-dynamic-select-statement?answertab=votes#tab-top" rel="nofollow">https://stackoverflow.com/questions/19992334/how-to-listen-to-n-channels-dynamic-select-statement?answertab=votes#tab-top</a></p></pre>

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

495 次点击  
加入收藏 微博
0 回复
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传