3 回答
TA贡献1785条经验 获得超4个赞
为了表示异步任务的结束,关闭通道是一种最佳实践,这对于防止导致各种死锁的许多未使用非常重要。在你的原始代码中,我会写而不是记住,在关闭的不阻塞上读取并始终返回零值,这就是诀窍。close(quite)
quit <- struct{}{}
无论如何,从这个开始,解决您的问题的一个优雅方法是使用两者和.context.Context
time.After
time.After
将帮助您阻止可选的任务集。
context.Context
更适合处理这种信号。
https://play.golang.org/p/ZVsZw3P-YHd
package main
import (
"context"
"log"
"time"
)
func main() {
log.Println("start")
defer log.Println("end")
ctx, cancel := context.WithCancel(context.Background())
tasks := make(chan struct{})
go func() {
time.Sleep(1 * time.Second) // a job
tasks <- struct{}{}
}()
go func() {
time.Sleep(3 * time.Second) // a job
cancel()
}()
for {
select {
case <-ctx.Done():
log.Println("QUIT")
return
case <-tasks:
log.Println("Doing")
// do some long time jobs more than 10 seconds
select {
case <-ctx.Done():
return
case <-time.After(time.Second * 10):
}
}
}
}
TA贡献1946条经验 获得超3个赞
使用 [sync.等待组。
package main
import (
"fmt"
"sync"
"time"
)
func worker(msg string, duration time.Duration, doing bool, wg *sync.WaitGroup) {
defer wg.Done()
time.Sleep(duration)
fmt.Println(msg)
if doing {
time.Sleep(10 * time.Second)
}
}
func main() {
var wg sync.WaitGroup
msgs := [2]string{"QUIT", "Doing"}
durations := [2]time.Duration{3 * time.Second, 1 * time.Second}
doing := [2]bool{false, true}
for i, msg := range msgs {
wg.Add(1)
go worker(msg, durations[i], doing[i], &wg)
}
wg.Wait()
}
TA贡献1786条经验 获得超13个赞
第二个作业运行 10 秒,因此它将阻塞该时间的循环,并且在此作业完成之前不会接收发送到通道的信号。quit
为了中断耗时的工作,也许你可以把它分成另一个goroutine。像这样的东西可以做到:
go func() {
for {
select {
case <-tasks:
fmt.Println("Doing")
// do some long time jobs more than 10 seconds
time.Sleep(10 * time.Second)
}
}
}()
<-quit
fmt.Println("QUIT")
- 3 回答
- 0 关注
- 84 浏览
添加回答
举报