循环输出dog cat fish一百次,要求使用三个goroutine分别代表dog, cat, fish。

package main

import (
	"fmt"
	"sync"
)

//dog cat fish 按这个输出一百句   第一题

var wg sync.WaitGroup

func main() {
	// counter use to count the output
	var counter int = 3
	dogch := make(chan struct{}, 1)
	catch := make(chan struct{}, 1)
	fishch := make(chan struct{}, 1)
	wg.Add(3)
	// let run the three goroutine

	// the origin of the goroutine to set dogch <- struct {}{}
	dogch <- struct{}{}

	go dog(dogch, counter, catch)
	go cat(catch, counter, fishch)
	go fish(fishch, counter, dogch)


	wg.Wait()
}

func dog(dogch chan struct{}, counter int, catch chan struct{})  {
	dogtimes := 0
	for dogtimes < counter {
		select {
		case <-dogch :
		fmt.Println("dog")
		dogtimes ++
		// let cat run
		catch <- struct{}{}
		}
	}
	wg.Done()

}

func cat(catch chan struct{}, counter int, fishch chan struct{})  {
	cattimes := 0
	for cattimes < counter{
		select {
		case <-catch :
			fmt.Println("cat")
			cattimes ++
			//let fish run
			fishch <- struct{}{}
		}
	}
	wg.Done()
}

func fish(fishch chan struct{}, counter int, dogch chan struct{})  {
	fishtimes := 0
	for fishtimes < counter {
		select {
		case <-fishch :
			fmt.Println("fish")
			fishtimes ++
			// let dog run
			dogch <- struct{}{}
		}
	}
	wg.Done()


//题解:
// 分别使用三个goroutine代表dog cat fish,由于携程执行的无顺序性,但是题目要求顺序循环输出,
// 所以,我们使用通道来实现阻塞,通过传值到通道中来实现顺序执行
// 首先定义了三个有缓冲通道 ,并设置了循环的次数counter
// counter use to count the output
//	var counter int = 3
//	dogch := make(chan struct{}, 1)
//	catch := make(chan struct{}, 1)
//	fishch := make(chan struct{}, 1)

// 然后对于每一个goroutine来说设置一个 for循环来执行counter次,里面采用for-select-case
// 如果该通道没值 则会阻塞在这个地方直到有值传进来。

//  // the origin of the goroutine to set dogch <- struct {}{}
//  dogch <- struct{}{} 这一句话是三个goroutin启动的触发条件。
//  第一个goroutine有值之后,执行第一个输出 dog,然后向catch里面传值,这个时候被阻塞的第一个goroutine//
//  得以激活,一次类推,直到把循环走完,每个goroutine都done了,程序结束