背景:
看到这样一个golang的面试题,大致是:
有三个函数分别打印,“dog”,“cat”,“fish”,
要求每个函数起一个goroutine,请按照dog,cat,fish的顺序,打印四次,输出到控制台。
思考:
其实这道题,就是在考察两点:
1.goroutine和channel的配合,使用来控制多个协程的执行顺序;
2.如何控制协程执行的次数;(sync包)
3.考虑扩展性和优雅
package main
import (
"fmt"
"sync"
)
func main() {
schedule(4, []func(){PrintDog, PrintCat, PrintFish}...)
}
func schedule(cnt int, fn ...func()) {
chList := make([]chan struct{}, len(fn)+1)
for ix := range chList {
chList[ix] = make(chan struct{})
}
wg := &sync.WaitGroup{}
for i := 0; i < len(fn); i++ {
wg.Add(1)
go func(index int) {
defer wg.Done()
for {
_, isOpening := <-chList[index]
if !isOpening {
close(chList[index+1])
return
}
fn[index]()
chList[index+1] <- struct{}{}
}
}(i)
}
wg.Add(1)
go func() {
defer wg.Done()
for i := 0; i < cnt; i++ {
fmt.Printf("---第%d次---\n", i+1)
chList[0] <- struct{}{}
<-chList[len(fn)]
if i == cnt-1 {
close(chList[0])
}
}
}()
wg.Wait()
}
func PrintDog() {
fmt.Println("Dog")
}
func PrintCat() {
fmt.Println("Cat")
}
func PrintFish() {
fmt.Println("Fish")
}
输出结果:
---第1次---
Dog
Cat
Fish
---第2次---
Dog
Cat
Fish
---第3次---
Dog
Cat
Fish
---第4次---
Dog
Cat
Fish
Process finished with the exit code 0