在GO语言中以异步方式获取URL列表。

huangapple go评论83阅读模式
英文:

GETing a list of urls in a async fashion in GO

问题

在我的GO应用程序中,我经常需要查询一个URL列表。由于GO是从底层开始异步的,所以这是使用这个功能的最佳场所。

解决这个问题的最佳方法是什么?我找到了一个博客提出的解决方案,但是当URL列表为空时它会失败。

谢谢!

英文:

I my GO application, I often need to query a list or urls. As GO is async from ground up, it is the perfect place to use this functionality.

What is the best way solve that? I found a blog proposing a solution but it fails with an empty list of urls.

Thanks!

答案1

得分: 2

我已经调整了你提供的博客链接中的代码,并使其对错误更具弹性。

下面的代码应该可以编译,并且应该处理边界情况,例如空的输入 urls 切片。

package main

import (
	"fmt"
	"net/http"
	"os"
	"time"
)

const timeout time.Duration = 3 * time.Second

var urls = []string{
	"http://golang.org/",
	"http://stackoverflow.com/",
	"http://i.wanta.pony/", // 应该会出错
}

type httpResponse struct {
	url      string
	response *http.Response
	err      error
}

func asyncHTTPGets(urls []string, ch chan *httpResponse) {
	for _, url := range urls {
		go func(url string) {
			resp, err := http.Get(url)
			ch <- &httpResponse{url, resp, err}
		}(url)
	}
}

func main() {
	responseCount := 0
	ch := make(chan *httpResponse)
	go asyncHTTPGets(urls, ch)
	for responseCount != len(urls) {
		select {
		case r := <-ch:
			if r.err != nil {
				fmt.Printf("获取 %s 时出错:%s\n", r.url, r.err)
			} else {
				fmt.Printf("%s 已获取\n", r.url)
			}
			responseCount++
		case <-time.After(timeout):
			os.Exit(1)
		}
	}
}

Playground

英文:

I've tweaked the code in the blog link you provided and made it slightly more resilient to error.

The code below should compile, and should handle boundary cases such as an empty input urls slice.

package main

import (
	&quot;fmt&quot;
	&quot;net/http&quot;
	&quot;os&quot;
	&quot;time&quot;
)

const timeout time.Duration = 3 * time.Second

var urls = []string{
	&quot;http://golang.org/&quot;,
	&quot;http://stackoverflow.com/&quot;,
	&quot;http://i.wanta.pony/&quot;, // Should error
}

type httpResponse struct {
	url      string
	response *http.Response
	err      error
}

func asyncHTTPGets(urls []string, ch chan *httpResponse) {
	for _, url := range urls {
		go func(url string) {
			resp, err := http.Get(url)
			ch &lt;- &amp;httpResponse{url, resp, err}
		}(url)
	}
}

func main() {
	responseCount := 0
	ch := make(chan *httpResponse)
	go asyncHTTPGets(urls, ch)
	for responseCount != len(urls) {
		select {
		case r := &lt;-ch:
			if r.err != nil {
				fmt.Printf(&quot;Error %s fetching %s\n&quot;, r.err, r.url)
			} else {
				fmt.Printf(&quot;%s was fetched\n&quot;, r.url)
			}
			responseCount++
		case &lt;-time.After(timeout):
			os.Exit(1)
		}
	}
}

Playground

答案2

得分: 0

由于您正在使用非缓冲通道,它将被阻塞,直到URL被处理完毕。

英文:

since you are using unbuffered channel, it's will be blocked until the url has been processed.

huangapple
  • 本文由 发表于 2014年2月21日 03:10:09
  • 转载请务必保留本文链接:https://go.coder-hub.com/21917258.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定