我有一個 LOOP,它對給定的鍵在內部進行散列并回傳結果,但在結果上,如果我有 1500 個 URL 串列進入 LOOP,它永遠不會回傳 1500 的結果,它總是回傳小于 1500。
我在下面做錯了什么:
if len(URLLists) > 0 {
var base = "https://example.com/query?="
var wg sync.WaitGroup
var mutex = sync.Mutex{}
wg.Add(len(URLLists))
for _, url := range URLLists {
// wg.Add(1) OR above for loop
go func() {
defer wg.Done()
hmac := "HMAX_123"
out := encoding.HexEncodeURL(hmac, url)
final := base out
list := Lists{
Old: url,
New: final,
}
mutex.Lock()
response.URL = append(response.URL, list)
mutex.Unlock()
}()
}
wg.Wait()
jR, err := json.Marshal(response)
if err != nil {
w.Write([]byte(`{"success": false, "url" : ""}`))
} else {
w.Write(jR)
}
return
}
我嘗試了兩種方法Add- 一個內部回圈為 1,一個外部回圈為總長度。
我希望函式回傳所有 1500 個 URL 串列,而不僅僅是“700、977、1123”隨機串列。
看起來 -wg.Wait()不是等待所有wg.Add- 添加
uj5u.com熱心網友回復:
你在這里有一個非常嚴重的比賽狀況:
response.URL = append(response.URL, list)
如果您要啟動多達 1500 個并發 Go 例程,您將有數百個例程都試圖同時執行這一行。它們將不斷覆寫對陣列的更改。
您需要使用 來保護將新資料插入到此切片中sync.Mutex,或者通過通道發送結果并讓單個 Go 例程從該通道讀取并附加到串列中。
uj5u.com熱心網友回復:
這個程式有幾個錯誤:
- 您正在 goroutine 中使用回圈變數。回圈變數在每次迭代時都被重寫,所以當 goroutine 使用 時
url,它可能已經移動到下一個 URL,因此你最終會得到多個 goroutine 散列相同的 URL。修理:
for _, url := range URLLists {
url:=url // Create a copy of the url
// wg.Add(1) OR above for loop
- 你有一個競爭條件。您必須保護對 的訪問,
response.URL因為它是由多個 goroutine 撰寫的。您可以使用互斥鎖:
lock:=sync.Mutex{}
for _,url:=...
...
lock.Lock()
response.URL = append(response.URL, list)
lock.Unlock()
更好的方法是通過通道發送這些。
轉載請註明出處,本文鏈接:https://www.uj5u.com/net/339721.html
