为什么 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 个结果,但只有一个执行并且进程结束。 有什么我想念的吗?新的去。 端点是一个通用的 API 即 returns json

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

fmt.Println(<-names)

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

要了解有关频道的更多信息,请参阅“Concurrency made easy" from Dave Cheney:

  • If you have to wait for the result of an operation, it’s easier to do it yourself.
  • Release locks and semaphores in the reverse order you acquired them.
  • Channels aren’t resources like files or sockets, you don’t need to close them to free them.
  • Acquire semaphores when you’re ready to use them.
  • Avoid mixing anonymous functions and goroutines
  • Before you start a goroutine, always know when, and how, it will stop

您启动了 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