variadic function looping through channels

agolangf · · 421 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<pre><code>func fanIn(inputs ...&lt;-chan string) &lt;-chan string { c := make(chan string) for cinput := inputs { // this line gives me error go func() {for { c &lt;- &lt;-cinput}}() } } </code></pre> <p>It&#39;s pretty self explanatory on what I am trying to do but it seems go lang doens&#39;t like how i do it. Why?</p> <hr/>**评论:**<br/><br/>dewey4iv: <pre><pre><code>func fanIn(inputs ...&lt;-chan string) &lt;-chan string { c := make(chan string) for _, in := range inputs { // this line gives me error go func(ch &lt;-chan string) { for { c &lt;-ch } }(in) } } </code></pre> <p>You were missing the range keyword :). I&#39;d also like to point out that you don&#39;t have any way of signaling when a channel is done sending.</p></pre>binaryblade: <pre><p>I like how you attempted to avoid closing over the loop variable but didn&#39;t.</p></pre>dewey4iv: <pre><p>Yeah, haha - I was in the middle of editing it and lost internet connection. Thanks for paying attention though!</p></pre>juniorsysadmin1: <pre><p>Hmm i don&#39;t think it&#39;s doing what I want it to do. </p> <p>I&#39;m trying to write a variadic function of the following function. </p> <pre><code>func fanIn(input1,input2 &lt;-chan string) &lt;-chan string{ c := make(chan string) go func() {for { c &lt;- &lt;-input1}}() go func() {for { c &lt;- &lt;-input2}}() return c } </code></pre> <p>So instead of 2 input it can take N inputs.</p> <p>I then have the following function in my testcode</p> <pre><code>func boring(msg string, s int) &lt;-chan string { // this return a receive-only channel of strings c := make(chan string) go func() { for i := 0; ; i++ { c &lt;- fmt.Sprintf(&#34;%s %d&#34;, msg, i) time.Sleep(time.Second * time.Duration(s)) } }() return c // return the channel to th e caller } </code></pre> <p>in main I have </p> <pre><code>joe:= boring(&#34;joe&#34;, 1) ann := boring(&#34;ann&#34;, 4) bla := fanIn(joe, ann) for i := 0; i &lt; 5; i++ { fmt.Println(&lt;-bla) } </code></pre> <p>Joe should appear 4 times and ann should appear once. The program end up having ann appear 5 times with 4 sec interval. </p> <p>My code is in <a href="https://pastebin.com/PCqVvASU" rel="nofollow">pastebin</a></p></pre>dewey4iv: <pre><p>Take a look at the output here -- is this more what you are looking for?</p> <p><a href="https://pastebin.com/Ti8fj7uY" rel="nofollow">https://pastebin.com/Ti8fj7uY</a></p></pre>juniorsysadmin1: <pre><p>yea that&#39;s what I was trying to achieve. </p></pre>dewey4iv: <pre><p>:thumbsup: </p></pre>mr-bosley: <pre><p>Surely this will memory leak, as the go routine inside...</p> <pre><code>for _, in := range inputs { // this line gives me error go func(ch &lt;-chan string) { for { c &lt;-ch } }(in) } </code></pre> <p>will never stop? There&#39;s a really good example of fan-in here. <a href="https://blog.golang.org/pipelines" rel="nofollow">https://blog.golang.org/pipelines</a></p></pre>dewey4iv: <pre><blockquote> <p>I&#39;d also like to point out that you don&#39;t have any way of signaling when a channel is done sending.</p> </blockquote> <p>Oh completely! That&#39;s what I was getting at with the above. </p></pre>jerf: <pre><p>Missing &#34;range&#34; on the inputs.</p> <p>While more complicated to work with, you may prefer either to use <a href="http://127.0.0.1:9000/pkg/reflect/#Select" rel="nofollow">reflect.Select</a> to do this all in one goroutine (as they may be <em>cheap</em> but they are not <em>free</em>), or conceivably, to try to make it so the destination channel is shared with the producers in a different way that prevents you from needing this. (Fan-in is a legitimate pattern, but it is not the first thing I&#39;d reach for. You&#39;re usually better off trying to get the channels to the right places in the first place rather than building complicated networks in Go.)</p></pre>LimEJET: <pre><p>did you just try to link your local copy of the documentation</p></pre>jerf: <pre><p>Yes. Yes I did. What, you can&#39;t get to it? :)</p></pre>LimEJET: <pre><p>I guess that&#39;s shame on me for not having a local doc server up constantly.</p></pre>jammerlt: <pre><p>Inputs is a slice, so cinput ends up being the index in the slice, and not the channel. You are also missing the range keyword and a return value. So for _, cinput := range inputs</p></pre>binaryblade: <pre><p>Just a heads up that channels in an API appear very infrequently in the Stdlib.</p></pre>uncle_bad_touches: <pre><p>Look at <a href="https://golang.org/pkg/reflect/#Select" rel="nofollow">https://golang.org/pkg/reflect/#Select</a>. This would allow you to monitor all the channels in a single goroutine.</p></pre>ChristophBerger: <pre><p>In addition to all the helpful comments so far, let me mention <a href="https://blog.golang.org/pipelines" rel="nofollow">this blog post</a> from the Go blog that discusses fan-in and fan-out.</p></pre>disq: <pre><p>Copying from an example I did for a quickstart session:</p> <pre><code>func copyData(in, out chan string) { for { // infinite loop out &lt;- &lt;-in // read from in, write to out } } func fanIn(channels ...chan string) chan string { out := make(chan string) for _, ch := range channels { // iterate all params go copyData(ch, out) } return out } </code></pre></pre>

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

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