Go 程序从 main 包的 main() 函数开始,在程序启动时,Go 程序就会为 main() 函数创建一个默认的 goroutine

所有 goroutinemain() 函数结束时会一同结束。 若在启用的goroutine中不使用WaitGroup的话会因为main函数已执行完,阻塞的函数与发送信号的函数会一同结束,不能真正实现阻塞的功能。

因此可以使用WaitGroup来实现阻塞的功能。

如下为不加WaitGroup时的版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
package main

import (
	"fmt"
	"time"
)

var closeCh = make(chan struct{})

func main() {
	// var wg sync.WaitGroup
	fmt.Println("start main func")

	// wg.Add(1)
	go func() {
		fmt.Println("waiting for signal")
		<-closeCh
		fmt.Println("got signal.")
		// wg.Done()
	}()

	// wg.Add(1)
	go func() {
		fmt.Println("preparing for signal:")
		for i := 0; i < 3; i++ {
			fmt.Println(">>>>")
			time.Sleep(time.Second * 1)
		}
		closeCh <- struct{}{}
		fmt.Println("sent signal.")
		// wg.Done()
	}()
	// wg.Wait()
}

执行结果

1
start main func // 只打印输出了这么一行

如下为加WaitGroup时的版本

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
package main

import (
	"fmt"
	"sync"
	"time"
)

var closeCh = make(chan struct{})

func main() {
	var wg sync.WaitGroup
	fmt.Println("start main func")

	wg.Add(1)
	go func() {
		fmt.Println("waiting for signal")
		<-closeCh
		fmt.Println("got signal.")
		wg.Done()
	}()

	wg.Add(1)
	go func() {
		fmt.Println("preparing for signal:")
		for i := 0; i < 3; i++ {
			fmt.Println(">>>>")
			time.Sleep(time.Second * 1)
		}
		closeCh <- struct{}{}
		fmt.Println("sent signal.")
		wg.Done()
	}()
	wg.Wait()
}

执行结果:

1
2
3
4
5
6
7
8
start main func
preparing for signal:
>>>>
waiting for signal
>>>>
>>>>
got signal.
sent signal.

参考: http://c.biancheng.net/view/93.html