1 回答

TA貢獻1828條經驗 獲得超3個贊
這已經通過評論得到了回答(請參閱mkopriva的評論),但讓我提供一個“答案化”版本。
首先,一個小小的旁白:
done := make(chan interface{})
我通??吹竭@里。由于從未發送過任何實際值,因此通道的類型并不重要,但是發送空值根本不占用空間,而發送空值則占用空間。1 個make(chan struct{})
struct
interface{}
現在,我們在這里要做的,在結束語中,2是:
等待(或至少假裝等待)某個服務器應答;
如果發生超時,請停止等待服務器;和
將我們的ID發送到結果渠道
或者如果頻道關閉(表明其他人打敗我們做任何事情),不要打擾上述任何一項。done
作為一個復雜因素,我們還將記錄我們等待了多長時間,即使我們沒有得到答案。
主要功能:
創建通道,其唯一目的是 d,以便從它接收立即返回它們在 EOF 處缺少值的零值;
done
close
剝離這些工人的一些數字(具體為10);
等待第一個交付結果(可能是由于超時,結果而導致的結果缺失)
關閉通道以使其余工作線程終止;和
done
打印最終結果。
我們感興趣的是為什么閉包的代碼是用代碼片段編寫的:
select { case <-done: case <-time.After(simulatedLoadTime): }
在其中。
這里的訣竅是預先評估其所有替代方案。因此,在開始選擇過程之前,它會評估通道,但也調用 。然后,等待具有值或位于通道末端并因此具有EOF的任何一個,以先發生者為準。select
done
time.After()
select
如果還沒有戈魯廷將結果發送回主戈魯廷,則該通道將不會關閉。此時,所有 goroutines 都將阻塞在通道上。但是所有的戈魯丁人也會叫.done
done
time.After
該代碼啟動一個 goroutine,經過一段時間后,它將在通道上發送當前時間。然后,它返回該通道。因此,這兩個操作中至少有一個將完成:通道將關閉或 get 關閉,并且由于 EOF,我們將在其上獲得零值,或者返回的通道將有一個時間發送到它,我們將收到該值。無論我們實際獲得哪個值,我們都會將值放在地板上,但是兩個運算符中的一個最終會解除阻塞的事實保證了這個goroutine最終能夠繼續。time.After
<-
done
time.After
<-
首先發生的事件將是通道的關閉或時間的接收。我們不知道這是哪一個,因為我們不知道通道關閉需要多長時間,但是時間的上限是我們傳遞給的持續時間有多長。也就是說,要么發生(最終),要么在我們選擇的時間之后,部分發生。其中之一肯定會發生。done
done
time.After
done
time.After
現在,如果我們不關心記錄我們花費的時間,我們可以把它寫成:
select { case <-done: return case <-time.After(simulatedLoadTime): // everything else happens here }
但請注意原始代碼中的注釋:
// do not want to return on <-done because we still want to log ...
因此,這解釋了缺乏.return
超時后,我們現在必須嘗試將我們的ID發送到主goroutine。但是,我們可能無法做到這一點:其他一些工作 goroutine 可能會擊敗我們發送,而主 goroutine 僅從通道讀取一個值。為了確保我們不會被困在這里,我們還有另一個.我們將嘗試發送我們的 ID,但如果頻道現在關閉或關閉,則停止。然后,我們將記錄并返回。select
done
1 個我一直認為Go應該有一個預先聲明的空結構類型,只是為了方便和風格的東西。我們在這里將其用于我們的頻道。我們將它用于僅作為集合而存在的映射,除了它們還將具有預先聲明的僅方便和樣式類型。但這完全是另一回事。done
阿拉伯數字這里沒有特別好的理由使用閉包。未導出的普通函數也可以正常工作。假設我們使用的是閉包,我們可以捕獲通道、值和通道,而不是將它們作為參數。我不清楚為什么作者選擇把它寫成一個可能成為函數的閉包,然后不去打擾閉包給我們帶來的任何好東西。done
wg *WaitGroup
result
- 1 回答
- 0 關注
- 106 瀏覽
添加回答
舉報