Is it only me or closing channels in Go is tricky ?

agolangf · · 474 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I have the feeling I keep running into deadlocks most of the time I try to use channels in Go. I have the feeling I can&#39;t keep the mental model on how to correctly signal the closing of the channel. Do you guys have any advise or tips to get it right ?</p> <hr/>**评论:**<br/><br/>riking27: <pre><p>The language basically requires that you have a single piece of code responsible for closing a given channel. Anything else is prone to panics.</p> <p>If you&#39;re having trouble figuring out:</p> <ul> <li>when multiple producers are all exhausted: use a sync.WaitGroup</li> <li>how to abandon pending items in the channel (when client goes away): use a <code>done chan struct{}</code>, such as provided by <code>context</code></li> </ul></pre>stormandsong: <pre><p><code>sync.Once</code> is also extraordinarily useful here.</p></pre>earthboundkid: <pre><p>The reason that double closing a channel causes a panic is that a design where multiple goroutines can close a channel is subject to a race condition. The language is trying to force you to use a better design for your concurrency. Once you’ve done it correctly once or twice, it gets easier to reason about. </p></pre>sybrandy: <pre><p>I believe the recommendation by Dave Cheney is that the sender is who closes the channel. This simplifies things greatly because since it&#39;s what will be sending on the channel, it can make sure you don&#39;t try to send on a closed channel.</p></pre>nsd433: <pre><blockquote> <p>deadlocks</p> </blockquote> <p>If communication flows two ways between two goroutines, via two channels, then you have one goroutine send and receive normally, and the second goroutine has to always be willing to yield while it is blocking wait to send to the first.</p> <p>In other words, the 1st goroutine can do</p> <pre><code>chan_r1_to_r2 &lt;- msg </code></pre> <p>while the 2nd goroutine must do</p> <pre><code>sent: for { select { case chan_to_r1 &lt;- msg: break sent case msg2 := &lt;- chan_r1_to_r2: // process or pend msg2 and go back to trying to send msg (if still applicable) } } </code></pre> <p>This is the same sort of idea as sorting your mutexes so they are always locked in a certain order to avoid deadlocks.</p> <p>Sometimes the design can be changed so that the job done by r2 can be split into an r2 which receives, and an r3 which sends. That results in cleaner code as long as the locking between r2 and r3 is minimal.</p> <p>The wrong way is to have r2 do</p> <pre><code>go func(msg) { chan_r2_to_r1 &lt;- msg } </code></pre> <p>because once several of these are pending there&#39;s no controlling the order in which they send to the channel.</p></pre>

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

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