登录
首页 >  Golang >  Go问答

协程返回的输出不完整

来源:stackoverflow

时间:2024-02-17 19:33:23 296浏览 收藏

本篇文章主要是结合我之前面试的各种经历和实战开发中遇到的问题解决经验整理的,希望这篇《协程返回的输出不完整》对你有很大帮助!欢迎收藏,分享给更多的需要的朋友学习~

问题内容

我有一个循环,它对给定的键进行内部散列并返回结果,但是在结果上,如果我有 1500 个 url 列表进入循环,它永远不会返回 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 - 添加


正确答案


该程序中有几个错误:

  1. 您正在 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
  1. 您存在竞争状况。您必须保护对 response.url 的访问,因为它是由多个 goroutine 写入的。您可以使用互斥锁:
lock:=sync.mutex{}
for _,url:=...
  ...
  lock.lock()
  response.url = append(response.url, list)
  lock.unlock()

更好的方法是通过通道发送这些内容。

这里有一个非常严重的竞争条件:

response.URL = append(response.URL, list)

如果您启动多达 1500 个并发 go 例程,则将有数百个例程同时尝试执行此行。他们将不断地覆盖对数组的更改。

您需要使用 sync.mutex 保护将新数据插入此切片,或者通过通道发送结果并使用单个 go 例程从该通道读取结果并将其附加到列表中。

今天带大家了解了的相关知识,希望对你有所帮助;关于Golang的技术知识我们会一点点深入介绍,欢迎大家关注golang学习网公众号,一起学习编程~

声明:本文转载于:stackoverflow 如有侵犯,请联系study_golang@163.com删除
相关阅读
更多>
最新阅读
更多>
课程推荐
更多>