[英]Go routine returns less results then the actual result
I have a LOOP that does the hashing inside for a given key and returns the result, but on Result, If I have 1500 list of URL that goes inside LOOP, it never returns the result of 1500, it returns always lesser then 1500.我有一个 LOOP,它对给定的键在内部进行散列并返回结果,但在结果上,如果我有 1500 个 URL 列表进入 LOOP,它永远不会返回 1500 的结果,它总是返回小于 1500。
What am I doing wrong in below:我在下面做错了什么:
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
}
I tried both method for Add
- one inside loop by 1 and one outside loop by total length.我尝试了两种
Add
方法 - 一个内部循环为 1,一个外部循环为总长度。
I want function to return all 1500 URL list and not just "700, 977, 1123" random list.我希望函数返回所有 1500 个 URL 列表,而不仅仅是“700、977、1123”随机列表。
It looks like - wg.Wait()
is not waiting for all the wg.Add
- added看起来 -
wg.Wait()
没有等待所有wg.Add
- 添加
There are a couple of errors in this program:这个程序有几个错误:
url
, it might have already moved on to the next URL, thus you end up with multiple goroutines hashing the same URL.url
,它可能已经移动到下一个 URL,因此你最终会得到多个 goroutine 散列相同的 URL。 To fix: for _, url := range URLLists {
url:=url // Create a copy of the url
// wg.Add(1) OR above for loop
response.URL
because it is being written by multiple goroutines.response.URL
访问,因为它是由多个 goroutine 编写的。 You can use a mutex:lock:=sync.Mutex{}
for _,url:=...
...
lock.Lock()
response.URL = append(response.URL, list)
lock.Unlock()
A better way would be to send these over a channel.更好的方法是通过通道发送这些。
You have a pretty serious race condition here:你在这里有一个非常严重的比赛状况:
response.URL = append(response.URL, list)
If you're starting as many as 1500 concurrent Go routines, you will have many hundreds of them all attempting to execute this line at once.如果您要启动多达 1500 个并发 Go 例程,您将有数百个例程都试图同时执行这一行。 They will be constantly overwriting changes to the array.
它们将不断覆盖对数组的更改。
You need to protect the insertion of new data into this slice with a sync.Mutex
, or be sending results over a channel and having a single Go routine reading from that channel and appending to the list.您需要使用
sync.Mutex
保护将新数据插入此切片,或者通过通道发送结果并让单个 Go 例程从该通道读取并附加到列表中。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.