<p>I have recently started learning go, and for a project I'm building I was wondering if there'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 := <- worker_chans[i int]:
read_in <- 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'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'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'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'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'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'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's a fun exercise but not that useful :P</p></pre>connor4312: <pre><p>reflect.Select is what you'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
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传