Prevent the main () function from stopping before completing the goroutings

Try this contrived example:

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++
    }
}

The output of this program will simply be "It will print." Exit goroutines printElo()and printHellowill not be radiated, because, in my opinion, the flow of functions main()completed before goroutines can even start running.

What is the idiomatic way to do similar code work in the Golang and not end prematurely?

+4
source share
4 answers

The simplest, cleanest, and most scalable way to do this is to use 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

"", sync.WaitGroup:

+8

, "" :

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()
}
+1

waitgroups. Goplayground I, .

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()
}
+1

, sync.WaitGroup . select{} main().

func main(){
    go routine()
    ...
    select{}
}

main(), , , , Ctrl-C. , , .

+1

Source: https://habr.com/ru/post/1672110/


All Articles