对这个人为的例子感到厌烦:
package main
import "fmt"
func printElo() {
fmt.Printf("Elo\n")
}
func printHello() {
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
go printElo()
go printHello()
i++
}
}
这个程序的输出只是“这将打印”。 goroutine printElo()
和printHello
的输出将不会被发出,因为我猜,main()
函数线程将在goroutines甚至有机会开始执行之前完成。
在Golang中使类似代码工作而不是过早终止的惯用方法是什么?
答案 0 :(得分:10)
最简单,最干净,最可扩展的&#34;这样做的方法是使用sync.WaitGroup
:
var wg = &sync.WaitGroup{}
func printElo() {
defer wg.Done()
fmt.Printf("Elo\n")
}
func printHello() {
defer wg.Done()
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
wg.Add(1)
go printElo()
wg.Add(1)
go printHello()
i++
}
wg.Wait()
}
输出(在Go Playground上尝试):
This will print.Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
Hello
Elo
简单&#34;规则&#34;使用sync.WaitGroup
执行此操作时要遵循:
WaitGroup.Add()
在go
陈述WaitGroup.Done()
延期,即使goroutine恐慌也会被调用WaitGroup
传递给其他函数(而不是使用全局变量),则必须传递指向它的指针,否则将复制WaitGroup
(这是一个结构),并且在原始Done()
方法
答案 1 :(得分:3)
如前所述,sync.WaitGroup
是生产代码中的正确方法。但在开发用于测试和调试目的时,您只需在末尾添加select{}
语句或main()
。
func main(){
go routine()
...
select{}
}
main()
然后永远不会返回,你会用例如Ctrl-C
来杀死它。它不是惯用的,从未用于生产,而是在开发时非常快速的黑客攻击。
答案 2 :(得分:1)
如果您只想玩结果,可以使用&#34; hack&#34;等待输入:
package main
import (
"fmt"
"bufio"
"os"
)
func printElo() {
fmt.Printf("Elo\n")
}
func printHello() {
fmt.Printf("Hello\n")
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
go printElo()
go printHello()
i++
}
reader := bufio.NewReader(os.Stdin)
reader.ReadString('\n')
}
如果想了解如何进行同步阅读有关同步包的信息:
package main
import (
"fmt"
"sync"
)
var wg sync.WaitGroup
func printElo() {
fmt.Printf("Elo\n")
wg.Done()
}
func printHello() {
fmt.Printf("Hello\n")
wg.Done()
}
func main() {
fmt.Printf("This will print.")
i := 0
for i < 10 {
wg.Add(2)
go printElo()
go printHello()
i++
}
wg.Wait()
}
答案 3 :(得分:1)
您可以使用sync package并查看waitgroups
。您可以查看有效的Goplayground I set up.
基本上
package main
import (
"fmt"
"sync"
)
//Takes a reference to the wg and sleeps when work is done
func printElo(wg *sync.WaitGroup) {
fmt.Printf("Elo\n")
defer wg.Done()
}
//Takes a reference to the wg and sleeps when work is done
func printHello(wg *sync.WaitGroup) {
fmt.Printf("Hello\n")
defer wg.Done()
}
func main() {
//Create a new WaitGroup
var wg sync.WaitGroup
fmt.Println("This will print.")
for i := 0; i < 10; i++ {
//Add a new entry to the waitgroup
wg.Add(1)
//New Goroutine which takes a reference to the wg
go printHello(&wg)
//Add a new entry to the waitgroup
wg.Add(1)
//New Goroutine which takes a reference to the wg
go printElo(&wg)
}
//Wait until everything is done
wg.Wait()
}