Can someone explain when the `sndMsg` function is called here?

blov · · 477 次点击    
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
<p>I was reading a set of slides on Go best practices:</p> <p><a href="https://talks.golang.org/2013/bestpractices.slide#33" rel="nofollow">https://talks.golang.org/2013/bestpractices.slide#33</a></p> <p>On the linked slide there is the code:</p> <pre><code> func broadcastMsg(msg string, addrs []string) error { errc := make(chan error) quit := make(chan struct{}) defer close(quit) for _, addr := range addrs { go func(addr string) { select { case errc &lt;- **sendMsg**(msg, addr): fmt.Println(&#34;done&#34;) case &lt;-quit: fmt.Println(&#34;quit&#34;) } }(addr) } for _ = range addrs { if err := &lt;-errc; err != nil { return err } } return nil } </code></pre> <p>I&#39;m still early on in my learning of Go. I can&#39;t see when the sndMsg() function, highlighted in bold, is called.</p> <p>I understand that the for {} loop will iterate indefinitely and in a proper application the quit channel would be used to exit from the for loop.</p> <p>In the select is sndMsg() called every time <code>case errc &lt;- ...</code> is evaluated?? Furthermore does this call to sndMsg() block the switch statement? Does it block the for loop therefore as well?</p> <hr/>**评论:**<br/><br/>Frakturfreund: <pre><p>In go, <code>select</code> and <code>switch</code> are different things, see <a href="https://golang.org/ref/spec#Select_statements" rel="nofollow">Select statements</a> in the Language Specification</p></pre>tommy144p: <pre><p>Thanks I&#39;ll read this.</p></pre>dchapes: <pre><blockquote> <p>I understand that the for {} loop will iterate indefinitely</p> </blockquote> <p>No they don&#39;t. Both <code>for</code> loops iterate <code>len(addrs)</code> times.</p></pre>tommy144p: <pre><p>Yes you&#39;re right. My bad :P</p></pre>MalkMalice: <pre><p>Have you read about go routines yet? The <code>go</code> keyword before <code>func(addr string) ...</code> is calling this inline function for every address in the <code>addrs</code> slice. The inline function is doing noting more then performing a <code>select</code> on the two channels <code>quit</code> and <code>sendMsg</code> (<code>sendMsg</code> is actually returning a channel).</p> <p>I think you should definitely take a look at go routines and channels. That&#39;s what you need to understand this piece of code.</p></pre>dchapes: <pre><blockquote> <p><code>sendMsg</code> is actually returning a channel</p> </blockquote> <p>No it isn&#39;t. It returns an <code>error</code> value that is sent on the <code>errc</code> channel.</p></pre>tommy144p: <pre><p>I have yeah. I see so there&#39;s a separate <code>select</code> running in a separate go routine for each <code>addr</code>?</p> <p>Therefore in the first evaluation of the select it will call <code>sndMsg()</code>? Will it hang here waiting for the return of sndMsg()? I&#39;m guessing it will. Once that returns, if there&#39;s no error then will it wait for a message on the quit chan?</p></pre>MalkMalice: <pre><p>Yes, a go routine is spawned for every address, this happens in the loop. Each go routine consists of this inline function taking the address. As <a href="/u/Frakturfreund" rel="nofollow">/u/Frakturfreund</a> said, Select is not Switch. Select will wait for either <code>sendMsg</code><strong>OR</strong> <code>quit</code> to return something and then continue.</p></pre>tommy144p: <pre><p>Cool ok. So if sndMsg was processing and the quit Chan received a message in the meantime, can the select handle watching both chans?</p></pre>Frakturfreund: <pre><p>Yes, in this example, select will »wait« until it can read from one of the two channels, and than execute the body of this case. Important note: if it can read from both, it will choose one <em>at random</em>.</p></pre>djherbis: <pre><p>The select doesn&#39;t start until all its arguments are fully evaluated.</p> <p>In this case sndMsg must complete, and return its error, before sending on the errc chan or recv from the quit channel.</p> <p>The easiest way to test this out is just to open the go playground <a href="https://play.golang.org/" rel="nofollow">https://play.golang.org/</a></p> <p>Paste the code and implement sndMsg as a &lt;-time.After(time.Second) call. You&#39;ll see that even if quit is ready, it&#39;ll still block for sndMsg to finish.</p></pre>

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

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