Is this a correct usage of channels?

agolangf · · 479 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I&#39;ve just started looking at go a few days ago, and I wanted to try rewriting an unwieldy set of python scripts that I have, in go.</p> <p>The object of the code is to read some files from Amazon S3, and process them line by line.</p> <p>This is a function I wrote, using the AWS GO SDK, to list a bucket, and return them in a channel. I&#39;m using channels to emulate python&#39;s generators, since the list can be very large</p> <pre><code>func ListS3(bucket, prefix string, client *s3.S3) chan string{ c := make(chan string) input := s3.ListObjectsInput{ Bucket: aws.String(bucket), Prefix: aws.String(prefix)} go func() { client.ListObjectsPages( &amp;input, func(p *s3.ListObjectsOutput, last bool) (shouldContinue bool) { for _, obj := range p.Contents{ c &lt;- *obj.Key } if last { close(c) } return true }) }() return c } </code></pre> <p>And I&#39;m using the function like this:</p> <pre><code>list := ListS3(bucket, path, svc) for key := range list { fmt.Println(key) } </code></pre> <hr/>**评论:**<br/><br/>dotaheor: <pre><p>Is client.ListObjectsPages a synced or asycned call? If it is a synced call, please put close(c) after it, for it is possible the callback passed to client.ListObjectsPages will never be called so that close(c) will be never called.</p></pre>ilogik: <pre><p>fair point, I&#39;ve added it</p></pre>Epolevne: <pre><p>If in your usage it&#39;s important to know that you got all the items then I would suggest adding some error handling since this is a network operation and will fail at some point. The current code may not return all the items of the S3 bucket and the caller cannot tell.</p></pre>ilogik: <pre><p>ListObjectsPages returns an error object. I&#39;m not really sure how I&#39;m supposed to pass that back, since it&#39;s being called in a goroutine.</p> <p>I had started by adding a second error return value to ListS3, but that doesn&#39;t make sense, because that only returns the channel, which happens immediately.</p> <p>Should I return the err through the channel?</p> <p>Do you have any examples code for this?</p></pre>Epolevne: <pre><p>You could use a struct on the channel that has an error and a string instead of just a string. </p></pre>danredux: <pre><p>Never start a goroutine without a plan to end it. If something goes wrong while iterating, the goroutine will stay forever. That&#39;s a leak.</p></pre>Veonik: <pre><p>I&#39;d say this is valid. The <a href="https://golang.org/src/text/template/parse/lex.go#L146" rel="nofollow">text/template package&#39;s lexer</a> does much the same, emitting a token via a channel to the parser as it reads them.</p></pre>jerf: <pre><p>The usage you have literally given us above is not &#34;invalid&#34;, but it is a useless use of channels. You could just as easily put the Println in the callback in directly.</p> <p>However, if you spawn a set of worker goroutines who all read from that channel and then do the work for the given bucket, you&#39;d have something useful. In this case you see why most Go network APIs are written to be synchronous; it keeps the code simple, and users of those APIs can easily add any other asynchronous/concurrent behaviors they want via goroutines.</p></pre>ilogik: <pre><p>Yes, that&#39;s the plan, to have workers processing the the resulting files.</p></pre>jerf: <pre><p>Cool, just wanted to be sure. It is not uncommon to see code posted by relatively new Go programmers that uselessly uses channels or spawns goroutines to worse than no effect. :)</p></pre>ilogik: <pre><p>that&#39;s exactly why I posted the question. I was mostly just using it as a replacement for generators for now.</p> <p>I&#39;ve picked this problem as my first go program because I thought it was a good use case for goroutines</p></pre>Yojihito: <pre><p>Do you need a code sample of a worker pool listening on a channel and doing func_x()?</p> <p>I&#39;ve done that for my last project, works quite well.</p></pre>ilogik: <pre><p>yeah, I&#39;d love that :)</p></pre>Yojihito: <pre><p><a href="https://play.golang.org/p/QnU1zOZrHJ" rel="nofollow">https://play.golang.org/p/QnU1zOZrHJ</a></p></pre>Morgahl: <pre><p>Small critique. Use a for range loop on the channel if there is only one channel you are listening to:</p> <p><a href="https://play.golang.org/p/xihPx1RWMb" rel="nofollow">https://play.golang.org/p/xihPx1RWMb</a></p> <p>This allows you to to close the channel, the workers will finish processing the workQueue and then exit. Always write your Goroutines with a way to exit when they are done :)</p></pre>ilogik: <pre><p>awesome!, thank you :)</p></pre>

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

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