Go例程中的有限循环

I am trying to execute two or more go routine synchronously after finish the topic

goroutines order of execution

And I write some code to test the go routines' behaviour (I treat it like a queue, BTW the go concurrency tutorial page not really help me)

package main

import (
        "fmt"
        "sync"
)

const size = 10
var vChan chan int = make(chan int, size)

func justSend(wg *sync.WaitGroup) {
        defer wg.Done()
        for i := 1; i <= 10; i++ {
                vChan <- i
        }
}

func justPrint(wg *sync.WaitGroup) {
        defer wg.Done()
        v := <- vChan
        fmt.Printf("%4d ", v);
}

func main() {
        wg := new(sync.WaitGroup)

        go func() {
                wg.Add(1)
                go justSend(wg)
                wg.Wait()
                wg.Add(size)
                go justPrint(wg)
                wg.Wait()
                close(vChan)
        }()
}

But it print nothing, should we design a go routine always have a infinite loop in there or we can't get it work properly?

(The piece of code is prepared for my real problem on building multiple websocket connection and testing our API server's response, so...I think passing bunch of channel which has same type between different function is quite annoying, so I set it globally)

You have put goroutine in main and main function finishes before your go routine finishes. So either do not use goroutine in main or use some kind of boolean receiving channel at the end of main which gets true when goroutine completed.

No, don't use infinite loop. Synchronization is better done with channels or the facilities of the sync package. The main() is a goroutine too (main one), so if main exits before other goroutines, your task remains unfinished. One way is to use sync.WaitGroup to wait for other goroutines to finish (see examples 1,2 and 3). Another way is using channels to wait for other goroutines to finish (see examples 4 and 5). I provide some examples so you may choose which one fits to your case:


1- One tx and multi rx (leave channel open), Try this:

package main

import (
    "fmt"
    "sync"
)

func main() {
    go tx()
    wg.Add(20)
    for i := 1; i <= 20; i++ {
        go rx()
    }
    wg.Wait()
}

func tx() {
    for i := 1; i <= 20; i++ {
        vChan <- i
    }
}

func rx() {
    defer wg.Done()
    fmt.Println(<-vChan)
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

2- One tx and one rx (leave channel open), Try this:

package main

import (
    "fmt"
    "sync"
)

func main() {
    go tx()
    wg.Add(1)
    go rx()
    wg.Wait()
}

func tx() {
    for i := 1; i <= 20; i++ {
        vChan <- i
    }
}

func rx() {
    defer wg.Done()
    for i := 1; i <= 20; i++ {
        fmt.Println(<-vChan)
    }
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

3- Closing channel to signal end of tx, Try this:

package main

import (
    "fmt"
    "sync"
)

func main() {
    go tx()
    wg.Add(1)
    go rx()
    wg.Wait()
}

func tx() {
    for i := 1; i <= 5; i++ {
        vChan <- i
    }
    close(vChan)
}

func rx() {
    defer wg.Done()
    for v := range vChan {
        fmt.Println(v)
    }
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

4- Closing channel to signal end of tx, using main goroutine for rx, try this:

package main

import (
    "fmt"
)

func main() {
    go tx()
    for v := range vChan {
        fmt.Println(v)
    }
}

func tx() {
    for i := 1; i <= 20; i++ {
        vChan <- i
    }
    close(vChan)
}

var vChan = make(chan int, 10)

5- Using quit channel, try this:

package main

import (
    "fmt"
)

func main() {
    go tx()
    go rx()
    <-quit
}
func rx() {
    for v := range vChan {
        fmt.Println(v)
    }
    quit <- struct{}{}
}
func tx() {
    for i := 10; i <= 15; i++ {
        vChan <- i
    }
    close(vChan)
}

var quit = make(chan struct{}, 1)
var vChan = make(chan int, 10)

output:

10
11
12
13
14
15

6- Multi tx multi rx, try this:

package main

import (
    "fmt"
    "sync"
)

func main() {
    wg.Add(5)
    for i := 1; i <= 5; i++ {
        go tx()
        go rx()
    }
    wg.Wait()
}

var n = 10

func tx() {
    vChan <- n
    n++
}

func rx() {
    defer wg.Done()
    fmt.Println(<-vChan)
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

7- Multi tx and one rx, try this:

package main

import (
    "fmt"
    "sync"
)

func main() {
    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go tx()
    }

    go rx()
    wg.Wait()
}

func rx() {
    for {
        fmt.Println(<-vChan)
        wg.Done()
    }
}

var n = 20

func tx() {
    vChan <- n
    n++
}

var wg sync.WaitGroup

var vChan = make(chan int, 10)

I hope this helps.