繁体   English   中英

为什么 goroutine 只作为等待组的一部分运行一次

[英]Why does the goroutine only run once as part of a waitgroup

func check(name string) string {
    resp, err := http.Get(endpoint + name)
    if err != nil {
        panic(err)
    }

    defer resp.Body.Close()

    body, err := ioutil.ReadAll(resp.Body)

    if err != nil {
        panic(err)
    }

    return string(body)

}

func worker(name string, wg *sync.WaitGroup, names chan string) {
    defer wg.Done()
    var a = check(name)
    names <- a
}

func main() {
    names := make(chan string)
    var wg sync.WaitGroup

    for i := 1; i <= 5; i++ {
        wg.Add(1)
        go worker("www"+strconv.Itoa(i), &wg, names)
    }
    fmt.Println(<-names)
}

预期结果将是 5 个结果,但只有一个执行并且过程结束。 有什么我想念的吗? go 的新功能。 端点是返回 json 的通用 API

你启动了 5 个 goroutine,但只读取了一个的输入。 此外,您不会等待 goroutines 结束。

// If there are only 5 goroutines unconditionally, you don't need the wg
for i := 1; i <= 5; i++ {
        go worker("www"+strconv.Itoa(i),  names)
}
for i:=1;i<=5;i++ {
   fmt.Println(<-names)
}

然而,如果你不知道你在等待多少个 goroutine,那么等待组是必要的。

for i := 1; i <= 5; i++ {
      wg.Add(1)
      go worker("www"+strconv.Itoa(i), &wg, names)
}
// Read from the channel until it is closed
done:=make(chan struct{})
go func() {
   for x:=range names {
     fmt.Println(x)
    }
    // Signal that println is completed
    close(done)
}()

// Wait for goroutines to end
wg.Wait()
// Close the channel to terminate the reader goroutine
close(names)
// Wait until println completes
<-done

您正在启动 5 个 goroutine,但仅从names通道读取一次。

fmt.Println(<-names)

一旦第一个通道读取完成, main()就会退出。
这意味着一切都在有时间执行之前停止。

要了解有关通道的更多信息,请参阅Dave Cheney的“轻松实现并发”:

  • 如果您必须等待操作的结果,那么您自己做会更容易。
  • 以您获得它们的相反顺序释放锁和信号量。
  • 通道不是文件或 sockets 之类的资源,您无需关闭它们即可释放它们。
  • 准备好使用信号量时获取信号量。
  • 避免混合匿名函数和 goroutines
  • 在你启动一个 goroutine 之前,总是知道它何时以及如何停止

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM