I am trying to execute two or more go routine synchronously after finish the topic
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.