我写了一个简单的GO程序,它应该启动3个GO例程。但是,GO例程无法启动。
请注意,此情况与此帖中的描述者不同:
Why is my goroutine not executed?
程序应该等待GO例程结束执行......因此,程序应该永远等待(因为例程永远不会停止)。
package main
import (
"fmt"
"net"
"os"
"time"
"sync"
)
func main() {
wg := sync.WaitGroup{}
fmt.Print("Starting 3 clients\n")
for i:=0; i<3; i++ {
client := func(inName string) {
fmt.Printf("Client <%s> started\n", inName)
wg.Add(1)
conn, err := net.Dial("tcp", ":8000")
if err != nil {
fmt.Printf("[%s] Error while connecting to the server: %s", inName, err.Error())
os.Exit(1)
}
n := 0
sleepDuration, _ := time.ParseDuration("2s")
for {
message := fmt.Sprintf("[%s] > message %d\n", inName, n)
fmt.Printf("%s", message)
_, err := conn.Write([]byte(message))
if nil != err {
fmt.Sprintf("[%s] Error while writing data to the socket: %s", inName, err.Error())
os.Exit(1)
}
time.Sleep(sleepDuration)
n++
}
}
name := fmt.Sprintf("Client%d", i)
fmt.Printf("Starting client <%s>...\n", name)
go client(name)
fmt.Print("Done\n")
}
wg.Wait()
}
结果:
Starting 3 clients
Starting client <Client0>...
Done
Starting client <Client1>...
Done
Starting client <Client2>...
Done
答案 0 :(得分:3)
正如this解决方案所说:
重要的是wg.Add()在go语句之前发生 防止竞争条件。以下也是正确的:
所以,你需要在go例程中取出wg.Add(1)
并在开始例行程序之前调用它。此外,在函数开头调用defer wg.Done()
,这样,它会将WaitGroup计数器减1。看看下面的代码。
package main
import (
"fmt"
"net"
"os"
"time"
"sync"
)
func main() {
wg := sync.WaitGroup{}
fmt.Print("Starting 3 clients\n")
for i:=0; i<3; i++ {
client := func(inName string) {
defer wg.Done() // added this line
fmt.Printf("Client <%s> started\n", inName)
conn, err := net.Dial("tcp", ":8000")
if err != nil {
fmt.Printf("[%s] Error while connecting to the server: %s", inName, err.Error())
os.Exit(1)
}
n := 0
sleepDuration, _ := time.ParseDuration("2s")
for {
message := fmt.Sprintf("[%s] > message %d\n", inName, n)
fmt.Printf("%s", message)
_, err := conn.Write([]byte(message))
if nil != err {
fmt.Sprintf("[%s] Error while writing data to the socket: %s", inName, err.Error())
os.Exit(1)
}
time.Sleep(sleepDuration)
n++
}
}
name := fmt.Sprintf("Client%d", i)
fmt.Printf("Starting client <%s>...\n", name)
wg.Add(1) // moved this line
go client(name)
fmt.Print("Done\n")
}
wg.Wait()
}