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 關注
- 405 瀏覽
添加回答
舉報