为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
桃花长相依 2023-06-26 16:21:23
我正在使用 Golang,我创建了这个小应用程序来使用 goroutine 进行多个并发 api 调用。当应用程序工作时,调用完成后,应用程序会卡住,这是有道理的,因为它无法退出范围c循环,因为通道未关闭。我不知道在这种模式下哪里可以更好地关闭通道。package mainimport "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    }} 
查看完整描述

2 回答

?
jeck猫

TA贡献1909条经验 获得超7个赞

当没有更多的值要发送时,您将关闭通道,因此在本例中,是在所有checkUrlgoroutine 完成时关闭。


var wg sync.WaitGroup


func checkUrls(urls []string) {

    c := make(chan string)


    for _, link := range urls {

        wg.Add(1)

        go checkUrl(link, c)

    }


    go func() {

        wg.Wait()

        close(c)

    }()


    for msg := range c {

        fmt.Println(msg)

    }

}


func checkUrl(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

    }

}

(请注意,errorfromhttp.Get仅反映连接和协议错误。如果您也期望这些错误,那么它不会包含 http 服务器错误,您必须看到如何检查路径而不仅仅是主机。)


查看完整回答
反对 回复 2023-06-26
?
一只斗牛犬

TA贡献1784条经验 获得超2个赞

当使用通道和 goroutine 在 Go 中编写程序时,始终要考虑谁(哪个函数)拥有通道。我更喜欢让拥有通道的函数关闭它的做法。如果我要写这个,我会这样做,如下所示。

注意:处理此类情况的更好方法是扇出、扇入并发模式。

package main


import "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

    }

}


查看完整回答
反对 回复 2023-06-26
  • 2 回答
  • 0 关注
  • 134 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信