这也是最近的一道面试题,确实是之前对这一块的使用比较少,然后被难到了。当时面试的时候只是记得对goroutine
的控制方法只有sync.WaitGroup
这一种方法,但是这种方法是为了保证所有的goroutine
全部都正常完成而准备的,想要直接到点直接退出,后来总结了一下,通常应该是有以下三种方法(仅个人理解)。
time.Sleep() 方法
该方法其实是最简单的,但不知道为什么当时就没有想到…
func main() {
for i := 0; i < 5; i++ {
go func(i int) {
tmp := rand.Intn(10)
time.Sleep(time.Duration(tmp) * time.Second)
fmt.Println("I want to sleep ", tmp, " seconds!")
// c <- i
}(i)
}
time.Sleep(5 * time.Second)
}
这样实际上就可以完成了,主协程保证在5s后会自动退出,他的所有子协程都会跟着退出,该执行的执行,该退出的退出,就能够达到目标。
time.Ticker 方法
接下来再看一个进阶的方法。该方法使用了time.Ticker
作为定时器,保证到期后会自动执行相应的内容。
func main() {
ticker := time.NewTicker(5 * time.Second)
c := make(chan int, 5)
for i := 0; i < 5; i++ {
go func(i int) {
tmp := rand.Intn(10)
time.Sleep(time.Duration(tmp) * time.Second)
fmt.Println("I want to sleep", tmp, "seconds!")
c <- i
}(i)
}
for {
select {
case i := <-c:
fmt.Printf("The %d goroutine is done.\n", i)
case <-ticker.C:
fmt.Println("Time to go out!")
os.Exit(5)
}
}
}
通过一个for
循环对channel
的内容以及ticker
进行监控。当接收到对应内容的时候,执行相应的操作。
话外,这个时候想到了当时另一道面试题,
select
里面的操作是如何执行的?
- 这个问题其实早早就看过,这是一个坑,因为
select
后面的内容是随机执行的,当时面试愣是没想起来,唉,还是写的太少了。
context 方法
该方法应该也是可以实现的,但是本人还在摸索阶段,具体代码先不po出来了,大家可以一起思考一下。