Go语言通过goroutine和标准库高效处理并发HTTP请求。1. 使用sync.WaitGroup控制多个goroutine同步执行;2. 通过channel限制并发数并传递结果;3. 利用context实现超时与取消;4. 使用errgroup简化错误处理与任务取消。根据场景选择合适模式可提升性能与稳定性。

在Golang中处理并发HTTP请求是构建高性能网络服务的核心能力之一。Go语言通过轻量级的goroutine和丰富的标准库支持,使得并发编程变得简单高效。以下是几种常用的并发HTTP请求处理方法,适用于不同场景下的需求。
使用Goroutine发起多个HTTP请求
最直接的方式是为每个HTTP请求启动一个独立的goroutine。这种方式适合需要同时获取多个资源的场景,比如聚合多个API数据。
注意:需配合sync.WaitGroup控制主程序等待所有请求完成。
package mainimport ("fmt""net/http""sync")
func fetch(url string, wg *sync.WaitGroup) {defer wg.Done()resp, err := http.Get(url)if err != nil {fmt.Printf("Error fetching %s: %vn", url, err)return}defer resp.Body.Close()fmt.Printf("Fetched %s with status: %sn", url, resp.Status)}
func main() {var wg sync.WaitGroupurls := []string{"https://www.php.cn/link/4d2fe2e8601f7a8018594d98f28706f2","https://www.php.cn/link/5f4d36824abbbe0b96729728d035a7ae","https://www.php.cn/link/0ad3140ed0cf59e84008db87c8c1106c",}
for _, url := range urls { wg.Add(1) go fetch(url, &wg)}wg.Wait()
}
使用Channel收集结果与控制并发数
当请求数量较大时,直接启动大量goroutine可能导致资源耗尽。通过channel可以限制并发数量,并安全地传递结果和错误。
立即学习“go语言免费学习笔记(深入)”;
func limitedConcurrentFetch(urls []string, maxConcurrency int) { type result struct { url string err error code int }sem := make(chan struct{}, maxConcurrency)results := make(chan result, len(urls))for _, url := range urls { go func(u string) { sem <- struct{}{} // 获取信号量 resp, err := http.Get(u) if err != nil { results <- result{u, err, 0} } else { results <- result{u, nil, resp.StatusCode} resp.Body.Close() } <-sem // 释放信号量 }(url)}// 收集所有结果for range urls { res := <-results if res.err != nil { fmt.Printf("Failed %s: %vn", res.url, res.err) } else { fmt.Printf("Success %s: %dn", res.url, res.code) }}
}
使用Context控制超时与取消
在并发请求中引入context能有效避免长时间阻塞。可设置整体超时或单个请求的截止时间,提升系统响应性。
func fetchWithContext(ctx context.Context, url string) error { req, _ := http.NewRequestWithContext(ctx, "GET", url, nil) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() return nil}func main() {ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)defer cancel()
var wg sync.WaitGroupurls := []string{"https://httpbin.org/delay/1", "https://httpbin.org/delay/3"}for _, url := range urls { wg.Add(1) go func(u string) { defer wg.Done() err := fetchWithContext(ctx, u) if err != nil { fmt.Printf("Request failed or timed out for %s: %vn", u, err) } else { fmt.Printf("Success: %sn", u) } }(url)}wg.Wait()
}
使用errgroup简化错误处理
golang.org/x/sync/errgroup 提供了更简洁的并发控制方式,自动传播第一个返回的错误并取消其他任务。
import "golang.org/x/sync/errgroup"func main() {urls := []string{"https://www.php.cn/link/98a733901e53052474f2320d0a3a9473","https://www.php.cn/link/874b2add857bd9bcc60635a51eb2b697","https://www.php.cn/link/98a733901e53052474f2320d0a3a9473",}
g, ctx := errgroup.WithContext(context.Background())for _, url := range urls { url := url g.Go(func() error { req, _ := http.NewRequestWithContext(ctx, "GET", url, nil) resp, err := http.DefaultClient.Do(req) if err != nil { return err } defer resp.Body.Close() if resp.StatusCode != 200 { return fmt.Errorf("received non-200 status: %d", resp.StatusCode) } fmt.Printf("OK: %sn", url) return nil })}if err := g.Wait(); err != nil { fmt.Printf("One request failed: %vn", err)}
}
基本上就这些常见模式。选择哪种方式取决于具体需求:简单并发可用WaitGroup,需限流用channel加缓冲池,强调错误传播和取消则推荐errgroup + context组合。合理使用这些方法能让Go程序高效稳定地处理大量HTTP请求。不复杂但容易忽略的是超时控制和资源释放,务必在生产代码中落实。
以上就是如何在Golang中处理并发HTTP请求_Golang并发HTTP请求处理方法汇总的详细内容,更多请关注创想鸟其它相关文章!
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 chuangxiangniao@163.com 举报,一经查实,本站将立刻删除。
发布者:程序猿,转转请注明出处:https://www.chuangxiangniao.com/p/1418924.html
微信扫一扫
支付宝扫一扫