1. 程式人生 > 其它 >利用協程順序輸出"xxx",sync.WaitGroup使用注意!

利用協程順序輸出"xxx",sync.WaitGroup使用注意!

順序輸出123

// 實現順序輸出123
func TestPrintNum(t *testing.T) {
	w := sync.WaitGroup{}
	a := make(chan struct{},1)
	b := make(chan struct{})
	w.Add(2)
	go func() {
		defer w.Done()
		for i:=1;i<4;i++{
			<-a
			if i % 2 != 0 {
				fmt.Println(i)
			}
			b <- struct{}{}
		}
	}()
	go func() {
		defer w.Done()
		for i:=1;i<4;i++{
			<-b
			if i % 2 == 0 {
				fmt.Println(i)
			}
			a <- struct{}{}
		}
	}()
	a <- struct{}{}
	w.Wait()
}

順序輸出dog、cat、fish

// 三個協程順序輸出 dog、cat、fish 四次
func TestDogCatAndFish(t *testing.T) {
	wg := sync.WaitGroup{}
	wg.Add(3)
	dog := make(chan struct{},1)
	cat := make(chan struct{})
	fish := make(chan struct{})
	dog <- struct{}{}
	go PrintDog(&wg,dog,cat)
	go PrintCat(&wg,cat,fish)
	go PrintFish(&wg,fish,dog)
	wg.Wait()
}

func PrintDog(wg *sync.WaitGroup,dog,cat chan struct{})  {
	defer wg.Done()
	for i := 0;i < 4;i++ {
		<- dog
		fmt.Println("dog")
		cat <- struct{}{}
	}
}

func PrintCat(wg *sync.WaitGroup,cat,fish chan struct{})  {
	defer wg.Done()
	for i := 0;i < 4;i++ {
		<- cat
		fmt.Println("cat")
		fish <- struct{}{}
	}

}

func PrintFish(wg *sync.WaitGroup,fish,dog chan struct{})  {
	defer wg.Done()
	for i := 0;i < 4;i++ {
		<- fish
		fmt.Println("fish")
		dog <- struct{}{}
	}
}

sync.WaitGroup使用注意

在上面的順序輸出dog、cat、fish的例子中,將wg變數通過函式引數的方式傳遞到函式當中,一定注意需要傳遞指標型別!
因為在golang中如果傳遞的不是地址,則會進行值拷貝傳遞,導致在函式中呼叫的不是同一個物件,而主方法中的wg一直在等待,從而導致報錯。