anonymous struct and empty struct
http://play.golang.org/p/vhaKi5uVmm
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 | package main import"fmt" var battle = make(chan string) func warrior(name string, done chan struct{}) { select { case opponent := <-battle: fmt.Printf("%s beat %s ", name, opponent) case battle <- name: // I lost :-( } done <- struct{}{} } func main() { done := make(chan struct{}) langs := []string{"Go","C","C++","Java","Perl","Python"} for _, l := range langs { go warrior(l, done) } for _ = range langs { <-done } } |
[第一个问题]
1 | done <- struct{}{} |
我们如何以及为什么需要这个看起来很奇怪的结构? 它是空结构还是匿名结构? 我用谷歌搜索,但是找不到正确的答案或说明文档。
原始资料来自Andrew Gerrand的演讲
http://nf.wh3rd.net/10things/#10
这里
1 | make(chan struct{}) |
完成是struct {}类型的通道
所以我尝试了
1 | done <- struct{} |
但这是行不通的。 为什么我需要为这条线加一个括号?
1 | done <- struct{}{} |
[第二个问题]
1 | for _ = range langs { <-done } |
为什么我需要这条线? 我知道这行是必要的,因为没有这行,就没有输出。 但是,为什么这行呢? 什么使该代码有必要? 我知道
请注意,将struct {}用于推送到通道的类型(与int或bool相反)的一个有趣方面是,空结构的大小为... 0!
请参阅Dave Cheney最近发表的文章"空结构"(2014年3月)。
您可以创建任意数量的
但是您可以将其用于在go例程之间进行信号传输,如"好奇的频道"中所示。
并且您保留了与结构相关的所有其他优点:
- 您可以在其上定义方法(该类型可以是方法接收者)
- 您可以实现一个接口(使用您只在空结构上定义的上述方法)
- 作为一个单身
in Go you can use an empty struct, and store all your data in global variables. There will only be one instance of the type, since all empty structs are interchangeable.
例如,在定义空结构
Composite literals
Composite literals construct values for structs, arrays, slices, and
maps and create a new value each time they are evaluated. They consist
of the type of the value followed by a brace-bound list of composite
elements. An element may be a single expression or a key-value pair.
好问题,
在这种情况下,struct通道的整个要点只是表示完成了有用的事情。通道类型并不重要,他可以使用int或bool来实现相同的效果。重要的是,他的代码以同步方式执行,在此期间他正在做必要的簿记工作,以便在关键点发出信号并继续前进。
我同意
如果您有一个预先存在的对象,例如:
1 2 3 | type Book struct{ } |
您可以这样创建它:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | func warrior(name string, done chan bool) { select { case opponent := <-battle: fmt.Printf("%s beat %s ", name, opponent) case battle <- name: // I lost :-( } done <- true } func main() { done := make(chan bool) langs := []string{"Go","C","C++","Java","Perl","Python"} for _, l := range langs { go warrior(l, done) } for _ = range langs { <-done } } |
我们将
1.那么奇怪的
这只是将传递给通道的另一种类型。如果您熟悉以下内容,则这是一个空结构:
1 2 3 4 | type User struct { Name string Email string } |
2.用于循环使用
我们创建6个goroutines并在此行中在后台运行:
1 | for _, l := range langs { go warrior(l, done) } |
我们使用
如果我们不包括最后一个for行,则可能看不到任何输出(因为主goroutine在任何子goroutine执行
因此,我们等待所有goroutine完成(运行到最后,并向
我们在后台有6个goroutine,并使用for循环,我们等到所有goroutine发送一条消息,这意味着它已完成运行(因为