3 回答
TA贡献1871条经验 获得超13个赞
如果你想要的只是你的简洁选择,你可以通过生成一个调用方法并在完成后关闭/发送通道的例程来轻松地将阻塞功能转换为通道。
done := make(chan struct{})
go func() {
wg.Wait()
close(done)
}()
select {
case <-done:
// All done!
case <-time.After(500 * time.Millisecond):
// Hit timeout.
}
TA贡献1864条经验 获得超6个赞
将您的结果发送到一个缓冲通道,足以获取所有结果,而不会阻塞,并在主线程的 for-select 循环中读取它们:
func work(msg string, d time.Duration, ret chan<- string) {
time.Sleep(d) // Work emulation.
select {
case ret <- msg:
default:
}
}
// ...
const N = 2
ch := make(chan string, N)
go work("printed", 100*time.Millisecond, ch)
go work("not printed", 1000*time.Millisecond, ch)
timeout := time.After(500 * time.Millisecond)
loop:
for received := 0; received < N; received++ {
select {
case msg := <-ch:
fmt.Println(msg)
case <-timeout:
fmt.Println("timeout!")
break loop
}
}
游乐场:http : //play.golang.org/p/PxeEEJo2dz。
TA贡献1966条经验 获得超4个赞
另一种方法是在内部对其进行监控,您的问题是有限的,但我假设您正在通过循环启动 goroutines,即使您不是,您也可以重构它来为您工作,但您可以这样做这两个示例之一,第一个将超时每个请求单独超时,第二个将超时整批请求,如果时间过长则继续
var wg sync.WaitGroup
wg.Add(1)
go func() {
success := make(chan struct{}, 1)
go func() {
// send your request and wait for a response
// pretend response was received
time.Sleep(5 * time.Second)
success <- struct{}{}
// goroutine will close gracefully after return
fmt.Println("Returned Gracefully")
}()
select {
case <-success:
break
case <-time.After(1 * time.Second):
break
}
wg.Done()
// everything should be garbage collected and no longer take up space
}()
wg.Wait()
// do whatever with what you got
fmt.Println("Done")
time.Sleep(10 * time.Second)
fmt.Println("Checking to make sure nothing throws errors after limbo goroutine is done")
或者,如果您只是想要一个通用的简单方法来超时所有请求,您可以执行以下操作
var wg sync.WaitGroup
waiter := make(chan int)
wg.Add(1)
go func() {
success := make(chan struct{}, 1)
go func() {
// send your request and wait for a response
// pretend response was received
time.Sleep(5 * time.Second)
success <- struct{}{}
// goroutine will close gracefully after return
fmt.Println("Returned Gracefully")
}()
select {
case <-success:
break
case <-time.After(1 * time.Second):
// control the timeouts for each request individually to make sure that wg.Done gets called and will let the goroutine holding the .Wait close
break
}
wg.Done()
// everything should be garbage collected and no longer take up space
}()
completed := false
go func(completed *bool) {
// Unblock with either wait
wg.Wait()
if !*completed {
waiter <- 1
*completed = true
}
fmt.Println("Returned Two")
}(&completed)
go func(completed *bool) {
// wait however long
time.Sleep(time.Second * 5)
if !*completed {
waiter <- 1
*completed = true
}
fmt.Println("Returned One")
}(&completed)
// block until it either times out or .Wait stops blocking
<-waiter
// do whatever with what you got
fmt.Println("Done")
time.Sleep(10 * time.Second)
fmt.Println("Checking to make sure nothing throws errors after limbo goroutine is done")
这样你的 WaitGroup 将保持同步,你不会有任何 goroutines 处于不确定状态
http://play.golang.org/p/g0J_qJ1BUT在这里试试你可以改变周围的变量以查看它的工作方式不同
编辑:我在移动设备上如果有人可以修复格式,那将是非常感谢。
- 3 回答
- 0 关注
- 350 浏览
添加回答
举报