本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,实战演示如何使用 Goroutine 和 Channel,实现多协程并发抓取网页内容,提升网络请求效率,为构建爬虫、内容聚合器、API 批量采集器打下基础。


一、实战背景

在互联网项目中,我们常需要批量获取多个网页的内容,例如:

  • • 爬虫程序抓取网页 HTML
  • • 数据聚合服务请求多个 API
  • • 批量检测多个 URL 的可用性

如果逐个请求(串行),效率将非常低下。Go 天生支持高并发,我们可以用 Goroutine 实现 多协程并发下载网页内容,显著提高吞吐能力。


二、实战目标

我们将构建一个小型并发网页下载器,具备以下能力:

  1. 1. 输入一组网址列表
  2. 2. 使用 Goroutine 并发请求多个网页
  3. 3. 使用 Channel 收集下载结果
  4. 4. 打印成功/失败状态与网页内容摘要
  5. 5. 支持 WaitGroup 等待所有任务完成

三、完整代码实现

package mainimport ("fmt""io""net/http""strings""sync""time"
)type Result struct {URL    stringStatus stringLength intError  error
}// 下载网页内容并写入结果通道
func fetchURL(url string, wg *sync.WaitGroup, resultCh chan<- Result) {defer wg.Done()client := http.Client{Timeout: 5 * time.Second,}resp, err := client.Get(url)if err != nil {resultCh <- Result{URL: url, Status: "请求失败", Error: err}return}defer resp.Body.Close()body, err := io.ReadAll(resp.Body)if err != nil {resultCh <- Result{URL: url, Status: "读取失败", Error: err}return}resultCh <- Result{URL:    url,Status: resp.Status,Length: len(body),}
}func main() {urls := []string{"https://example.com","https://httpbin.org/get","https://golang.org","https://nonexistent.example.com", // 故意的错误URL}var wg sync.WaitGroupresultCh := make(chan Result, len(urls))// 启动多个下载协程for _, url := range urls {wg.Add(1)go fetchURL(url, &wg, resultCh)}// 等待所有任务完成后关闭通道go func() {wg.Wait()close(resultCh)}()// 读取结果for res := range resultCh {if res.Error != nil {fmt.Printf("[失败] %s:%v\n", res.URL, res.Error)} else {snippet := fmt.Sprintf("%d 字节", res.Length)if res.Length > 0 {snippet = fmt.Sprintf("%s 内容预览:%s", snippet, strings.TrimSpace(string([]byte(res.URL)[:min(50, res.Length)])))}fmt.Printf("[成功] %s:%s\n", res.URL, snippet)}}fmt.Println("所有网页请求已完成。")
}func min(a, b int) int {if a < b {return a}return b
}

四、输出示例

[成功] https://example.com:1256 字节 内容预览:https://example.com
[成功] https://httpbin.org/get:349 字节 内容预览:https://httpbin.org/get
[成功] https://golang.org:3578 字节 内容预览:https://golang.org
[失败] https://nonexistent.example.com:Get "https://nonexistent.example.com": dial tcp: ...
所有网页请求已完成。

五、重点知识点讲解

1. 使用 Goroutine 启动并发请求

go fetchURL(url, &wg, resultCh)

每个网页请求都是一个轻量级的线程(协程),同时运行,最大化资源利用。


2. 使用 sync.WaitGroup 等待所有任务完成

WaitGroup 是 Goroutine 的最佳搭档,确保主线程不会提前退出。

wg.Add(1)
defer wg.Done()

3. 使用带缓冲的 Channel 收集结果

resultCh := make(chan Result, len(urls))

避免协程阻塞,收集所有结果后统一处理。


4. 设置请求超时

使用 http.Client{ Timeout: ... } 可防止因某个 URL 卡住导致整体阻塞。


5. 防止通道未关闭阻塞

一定要在所有任务完成后关闭结果通道:

go func() {wg.Wait()close(resultCh)
}()

六、可扩展方向

这个简单的并发网页下载器可以继续扩展为:

功能方向实现建议
限制最大并发数使用带缓冲的 chan struct{} 控制令牌
下载网页保存文件使用 os.Create 写入 HTML 文件
支持重试机制封装带重试的请求逻辑
使用 context 控制取消或超时实现更复杂的任务调度系统
支持代理设置 Transport.Proxy 实现

七、小结

通过本篇案例你掌握了:

✅ 使用 Goroutine 启动并发任务
✅ 使用 Channel 汇总任务结果
✅ 使用 WaitGroup 管理协程生命周期
✅ 网络请求的错误处理与超时机制

这为你实现一个功能完善的高并发爬虫、网页检测器或 API 批量处理工具奠定了基础。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。
如若转载,请注明出处:http://www.pswp.cn/web/91871.shtml
繁体地址,请注明出处:http://hk.pswp.cn/web/91871.shtml
英文地址,请注明出处:http://en.pswp.cn/web/91871.shtml

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

分享链接实现状态共享

有这么一个场景&#xff1a;就是有一些列表页面&#xff0c;然后上面是有一些筛选项的&#xff0c;我去对这个列表做了一些筛选出来一个结果&#xff0c;然后我想把这个链接&#xff0c;或者说把这个筛选结构给分享出去&#xff0c;让别人在打开这个页面的时候&#xff0c;也是…

Fay数字人如何使用GPT-SOVITS进行TTS转换以及遇到的一些问题

一、GPT-SoVITS 简介 GPT-SoVITS 是一款开源的语音合成&#xff08;TTS&#xff09;工具&#xff0c;结合了 GPT 模型的文本理解能力与 SoVITS&#xff08;Sound of Voice In Text-to-Speech&#xff09;的声纹模拟技术&#xff0c;能够实现高自然度、个性化的语音合成。它支持…

HTML 颜色值

HTML 颜色值 引言 在网页设计和开发中,颜色是一个重要的元素,它能够帮助用户更好地理解内容,提升视觉效果。HTML 颜色值是用于指定网页中元素颜色的一种标准表示方法。本文将详细介绍 HTML 颜色值的种类、表示方法以及在实际应用中的使用技巧。 HTML 颜色值种类 HTML 颜…

关于记录一下“bug”,在做图片上传的时候出现的小问题

项目场景&#xff1a;之前的话写过csdn&#xff0c;最近出现了一些小事情&#xff0c;所以耽误了好久没有更新&#xff0c;最近把以前的项目拿出来然后改了下环境就出现了一些问题&#xff0c;该项目使用SpringBoot3.5 SpringMVC Mybatis-Plus3.5.0&#xff0c;然后权限控制采…

数据结构:基础知识和链表①

一、概念程序数据结构算法1.描述数据存储和操作的结构 2.操作数据对象的方法二、衡量代码的质量和效率 无论代码操作数据量多大&#xff0c;希望程序代码的运行时间保持恒定 随着数据的增长&#xff0c;程序运行时间缓慢增长随着数据的增长&#xff0c;程序运…

进阶向:自动化天气查询工具(API调用)

自动化天气查询工具&#xff08;API调用&#xff09;完全指南天气数据是日常生活中经常需要查询的信息之一。本教程将介绍如何使用Python编写一个自动化天气查询工具&#xff0c;通过调用开放的天气API获取实时天气数据。这个工具适合完全不懂编程的新手学习&#xff0c;将从最…

【ROS2】常用命令

1、目录结构在 ROS 2 包中&#xff0c;launch、urdf、rviz&#xff08;通常指 RViz 配置文件&#xff09;、config 等文件夹应直接放在包的根目录下&#xff08;与 robot_arm/ Python 模块目录同级&#xff09;。这是 ROS 2 社区的通用约定&#xff0c;便于工具&#xff08;如 …

基础组件(三):mysql连接池

文章目录一、MySQL连接池设计1. 连接池解决了什么问题&#xff1f;连接池的作用 &#xff08;好处&#xff09;为什么不创建多条连接而用连接池2. 同步和异步连接池的区别同步连接池&#xff08;场景局限&#xff0c;应用服务器启动时初始化资源&#xff09;异步连接池&#xf…

FI文件包含漏洞

本地文件包含&#xff08;LFI&#xff09;文件包含开发人员将可重复使用的内容写到单个文件中&#xff0c;使用时直接调用此文件&#xff0c;无需再次编写&#xff0c;这种调用文件的过程一般被称为文件包含。这样编写代码能减少代码冗余&#xff0c;降低代码后期维护难度&…

rapidocr_web v1.0.0发布了

建立RapidOCRWeb独立仓库 终于将web这块代码移了出来&#xff0c;成立了独立仓库RapidOCRWeb (https://github.com/RapidAI/RapidOCRWeb )。这样以来&#xff0c;RapidOCR仓库下的各个衍生项目均有自己的独立仓库&#xff0c;可以单独控制发版和维护。这也算是为RapidOCR减负了…

Arduino IDE离线安装ESP8266板管理工具

文章目录概要官网地址开发板管理地址安装ESP8266开发板支持离线安装额外记录NODE启动服务概要 Arduino IDE离线安装ESP8266板管理工具&#xff0c;在线安装因为网络或者https的问题不能安装 官网地址 Adruino&#xff1a;https://www.arduino.cc/ ESP8266项目&#xff1a;<…

两款免费数据恢复软件介绍,Win/Mac均可用

数据已成为我们生活与工作中不可或缺的重要组成部分。无论是珍贵的家庭照片、关键的工作文档&#xff0c;还是重要的学习资料&#xff0c;都以数据的形式存储在各类设备中。然而&#xff0c;数据丢失的情况却时常发生&#xff0c;可能是误操作删除&#xff0c;可能是设备意外损…

Java开发中敏感信息加密存储全解析:筑牢数据安全防线

Java开发中敏感信息加密存储全解析&#xff1a;筑牢数据安全防线 一、引言 1.1 敏感信息存储的现状与挑战 在数字化时代&#xff0c;数据已然成为企业和组织的核心资产之一&#xff0c;而敏感信息的存储更是重中之重。从日常的用户登录密码、身份证号码&#xff0c;到金融领域…

list的使用和模拟

(一)list的了解 (1)简单了解 list的文档介绍 list是基于双向链表的序列式容器&#xff0c;支持双向迭代和任意位置的常数时间插入删除&#xff0c;相比 array、vector 等容器在这类操作上更高效&#xff0c;但不支持随机访问&#xff08;访问需线性遍历&#xff09;且因额外…

Docker 初学者需要了解的几个知识点 (五):建容器需要进一步了解的概念

之前在《Docker 初学者需要了解的几个知识点》几篇文章里&#xff0c;我们梳理了 Docker 的核心概念&#xff08;如镜像、容器、网络等&#xff09;&#xff0c;但在实际搭建 ThinkPHP 容器环境时&#xff0c;又遇到了一些更具体的术语和配置场景。这些内容和实操结合紧密&…

【数据结构】栈的顺序存储(整型栈、字符栈)

【数据结构】栈的顺序存储&#xff08;整型栈、字符栈&#xff09;一、栈的结构定义二、字符栈的初始化、入栈、出栈、判断是否栈为空、获取栈顶元素、获取栈的当前元素个数等操作三、整型栈的初始化、入栈、出栈、判断是否栈为空、获取栈顶元素、获取栈的当前元素个数等操作一…

【大模型实战】向量数据库实战 - Chroma Milvus

在 RAG&#xff08;检索增强生成&#xff09;场景中&#xff0c;非结构化数据&#xff08;文本、图像等&#xff09;的高效检索是核心需求。传统关系型数据库难以胜任&#xff0c;而向量数据库通过将数据转化为向量、基于相似度快速匹配&#xff0c;成为 RAG 的关键支撑。本文聚…

pytorch程序语句固定开销分析

深入探索PyTorch与Python的性能微观世界&#xff1a;量化基础操作的固定开销 在深度学习的性能优化工作中&#xff0c;开发者通常将目光聚焦于模型结构、算法效率和并行计算策略。然而&#xff0c;在这些宏观优化的背后&#xff0c;构成我们代码的每一条基础语句——无论是PyTo…

ABP VNext + CloudEvents:事件驱动微服务互操作性

ABP VNext CloudEvents&#xff1a;事件驱动微服务互操作性 &#x1f680; &#x1f4da; 目录ABP VNext CloudEvents&#xff1a;事件驱动微服务互操作性 &#x1f680;一、引言 ✨☁️ TL;DR&#x1f4da; 背景与动机&#x1f3d7;️ 整体架构图二、环境准备与依赖安装 &am…

软件测试测评公司关于HTTP安全头配置与测试?

浏览器和服务器之间那几行看不见的HTTP安全头配置&#xff0c;往往是抵御网络攻击的关键防线。作为软件测试测评公司&#xff0c;我们发现超过六成的高危漏洞源于安全头缺失或误配。别小看这些响应头&#xff0c;它们能直接掐断跨站脚本、点击劫持、数据嗅探的攻击路径。五条命…