GO例程为什么不启动?

时间:2018-04-03 08:37:06

标签: go

我写了一个简单的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

1 个答案:

答案 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()
}