走例程:Making concurrent API requests

标签 go concurrency channel goroutine

我试图了解 channel 和协程,并尝试编写一个协程来向服务器发出并发 API 请求

但是当我使用 goroutine 运行代码时,它似乎花费了与没有 goroutine 相同的时间。

func sendUser(user string, ch chan<- string)  {
    resp,err := http.get("URL"/user)
    //do the processing and get resp=string
    ch <- resp
}


func AsyncHTTP(users []string) ([]string, error) {
    ch := make(chan string)
    var responses []string
    var user string

    for _ , user = range users {
        go sendUser(user, ch)

        for {
            select {
            case r := <-ch:
                if r.err != nil {
                    fmt.Println(r.err)
                }
                responses = append(responses, r)
                **//Is there a better way to show that the processing of response is complete**?
                if len(responses) == len(users) { 
                    return responses, nil
                }
            case <-time.After(50 * time.Millisecond):
                fmt.Printf(".")
            }
        }
    }
    return responses, nil
}

问题:

  1. 即使我使用了 goroutine,请求完成时间与没有 goroutine 时一样吗?我对 goroutine 做错了什么吗?

  2. 为了告诉作业不要再在这里等待,我正在使用:

    if len(responses) == len(users)
    

    有没有更好的方法来表明response的处理完成,告诉ch不要再等待了?

  3. 什么是 wait.Syncgroup?我如何在我的 goroutine 中使用它?

最佳答案

我可能会做这样的事情..

func sendUser(user string, ch chan<- string, wg *sync.WaitGroup) {
    defer wg.Done()
    resp, err := http.Get("URL/" + user)
    if err != nil {
        log.Println("err handle it")
    }
    defer resp.Body.Close()
    b, err := ioutil.ReadAll(resp.Body)
    if err != nil {
        log.Println("err handle it")
    }
    ch <- string(b)
}

func AsyncHTTP(users []string) ([]string, error) {
    ch := make(chan string)
    var responses []string
    var user string
    var wg sync.WaitGroup
    for _, user = range users {
        wg.Add(1)
        go sendUser(user, ch, &wg)
    }

    // close the channel in the background
    go func() {
        wg.Wait()
        close(ch)
    }()
    // read from channel as they come in until its closed
    for res := range ch {
        responses = append(responses, res)
    }

    return responses, nil
}

它允许在发送时从 channel 中读取。通过使用 WaitGroup ,我将知道何时关闭 channel 。通过将 waitgroup 和 close 放在一个 goroutine 中,我可以“实时”地从 channel 中读取而不会阻塞。

关于走例程:Making concurrent API requests,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45337881/

相关文章:

go - 关闭 channel 与发送例如一个空结构?

go - go 例程 channel 中的同步问题

exception - 如何从外部包中的异步 panic 中恢复

windows - 在 Windows 上安装 PacketBeat

c# - List<T> 并发删除和添加

java - Fork Join 优化

java - 核心java中的原子问题

conda - 将 channel_priority 设置为 "strict"是否会影响所有 Conda 环境?

go - 惯用的 goroutine 终止和错误处理

http - 进行多次 response.WriteHeader 调用