<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 <- **sendMsg**(msg, addr):
fmt.Println("done")
case <-quit:
fmt.Println("quit")
}
}(addr)
}
for _ = range addrs {
if err := <-errc; err != nil {
return err
}
}
return nil
}
</code></pre>
<p>I'm still early on in my learning of Go. I can'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 <- ...</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'll read this.</p></pre>dchapes: <pre><blockquote>
<p>I understand that the for {} loop will iterate indefinitely</p>
</blockquote>
<p>No they don't. Both <code>for</code> loops iterate <code>len(addrs)</code> times.</p></pre>tommy144p: <pre><p>Yes you'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'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'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'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'm guessing it will. Once that returns, if there'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'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 <-time.After(time.Second) call. You'll see that even if quit is ready, it'll still block for sndMsg to finish.</p></pre>
这是一个分享于 的资源,其中的信息可能已经有所发展或是发生改变。
入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889
- 请尽量让自己的回复能够对别人有帮助
- 支持 Markdown 格式, **粗体**、~~删除线~~、
`单行代码`
- 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
- 图片支持拖拽、截图粘贴等方式上传