迭代通道时关闭通道的最佳时间

我正在使用 Golang,我创建了这个小应用程序来使用 goroutine 进行多个并发 api 调用。


当应用程序工作时,调用完成后,应用程序会卡住,这是有道理的,因为它无法退出范围c循环,因为通道未关闭。


我不知道在这种模式下哪里可以更好地关闭通道。


package main


import "fmt"

import "net/http"


func main() {

    links := []string{

        "https://github.com/fabpot",

        "https://github.com/andrew",

        "https://github.com/taylorotwell",

        "https://github.com/egoist",

        "https://github.com/HugoGiraudel",

    }


    checkUrls(links)

}


func checkUrls(urls []string) {

    c := make(chan string)


    for _, link := range urls {

        go checkUrl(link, c)

    }


    for msg := range c {

        fmt.Println(msg)

    }


    close(c) //this won't get hit

}


func checkUrl(url string, c chan string) {

    _, err := http.Get(url)


    if err != nil {

        c <- "We could not reach:" + url

    } else {

        c <- "Success reaching the website:" + url

    }


桃花长相依
浏览 135回答 2
2回答

jeck猫

当没有更多的值要发送时,您将关闭通道,因此在本例中,是在所有checkUrlgoroutine 完成时关闭。var wg sync.WaitGroupfunc checkUrls(urls []string) {&nbsp; &nbsp; c := make(chan string)&nbsp; &nbsp; for _, link := range urls {&nbsp; &nbsp; &nbsp; &nbsp; wg.Add(1)&nbsp; &nbsp; &nbsp; &nbsp; go checkUrl(link, c)&nbsp; &nbsp; }&nbsp; &nbsp; go func() {&nbsp; &nbsp; &nbsp; &nbsp; wg.Wait()&nbsp; &nbsp; &nbsp; &nbsp; close(c)&nbsp; &nbsp; }()&nbsp; &nbsp; for msg := range c {&nbsp; &nbsp; &nbsp; &nbsp; fmt.Println(msg)&nbsp; &nbsp; }}func checkUrl(url string, c chan string) {&nbsp; &nbsp; defer wg.Done()&nbsp; &nbsp; _, err := http.Get(url)&nbsp; &nbsp; if err != nil {&nbsp; &nbsp; &nbsp; &nbsp; c <- "We could not reach:" + url&nbsp; &nbsp; } else {&nbsp; &nbsp; &nbsp; &nbsp; c <- "Success reaching the website:" + url&nbsp; &nbsp; }}(请注意,errorfromhttp.Get仅反映连接和协议错误。如果您也期望这些错误,那么它不会包含 http 服务器错误,您必须看到如何检查路径而不仅仅是主机。)

一只斗牛犬

当使用通道和 goroutine 在 Go 中编写程序时,始终要考虑谁(哪个函数)拥有通道。我更喜欢让拥有通道的函数关闭它的做法。如果我要写这个,我会这样做,如下所示。注意:处理此类情况的更好方法是扇出、扇入并发模式。package mainimport "fmt"import "net/http"import "sync"func main() {    links := []string{        "https://github.com/fabpot",        "https://github.com/andrew",        "https://github.com/taylorotwell",        "https://github.com/egoist",        "https://github.com/HugoGiraudel",    }    processURLS(links)    fmt.Println("End of Main")}func processURLS(links []string) {    resultsChan := checkUrls(links)    for msg := range resultsChan {        fmt.Println(msg)    }}     func checkUrls(urls []string) chan string {    outChan := make(chan string)    go func(urls []string) {       defer close(outChan)       var wg sync.WaitGroup       for _, url := range urls {         wg.Add(1)          go checkUrl(&wg, url, outChan)       }       wg.Wait()    }(urls)    return outChan}func checkUrl(wg *sync.WaitGroup, url string, c chan string) {    defer wg.Done()    _, err := http.Get(url)    if err != nil {        c <- "We could not reach:" + url    } else {        c <- "Success reaching the website:" + url    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go