【go语言圣经1.6】

server/2025/3/17 7:09:24/

目标

学习如何利用 Go 语言的 goroutine 和 channel 实现并发网络请求;

理解如何使用 io.Copy 进行流式数据传输,从而避免一次性申请大缓冲区;

掌握如何通过时间测量和错误传递来构建一个健壮、并发友好的网络请求程序。

总之学习Go 语言并发编程的基础,为探索更复杂的并发场景和高级特性打基础。

概念

要点(案例)

这段代码实现了一个并发网络请求程序,其核心目标是同时发起多个 HTTP 请求,并在所有请求结束后报告每个请求的响应大小以及耗时。整体设计思路包括:

  • 并发执行:利用 Go 的 goroutine 机制同时发起多个网络请求,使程序总执行时间接近单个耗时最长的请求,而不是所有请求时间的总和。
  • 结果同步:通过 channel 在各个 goroutine 与主函数之间传递结果,确保最后输出时不会出现输出交错的问题。
  • 性能监控:通过记录程序开始时间和每个请求的耗时,直观地展示并发请求的效率。
  1. 主函数

    func main() {start := time.Now() // 记录程序开始时间ch := make(chan string) // 建一个用于传递字符串的channel// 针对命令行传入的每个URL,启动一个新的goroutine并发执行fetch函数for _,url := range os.Args[1:] {go fetch(url, ch) // 使用go关键字启动goroutine}// 循环接收所有goroutine传回的结果,保证每个请求都被处理for range os.Args[1:] {fmt.Println(<-ch)         // 从channel中接收结果并打印}// 打印整个程序的耗时,单位为秒fmt.Printf("%.2fs elapsed\n", time.Since(start).Seconds())}
    
    • goroutine
      • 是 Go 语言中轻量级的并发执行单元,可以理解为比线程更小的执行体。启动一个 goroutine 非常简单,只需在函数调用前加上 go 关键字。
        • go fetch(url, ch) 表示为每个 URL 启动一个新的并发执行实例,彼此之间互不干扰。
    • channel
      • 是一种用于不同 goroutine 之间通信的工具,通过发送和接收数据来进行同步。
      • 本例中创建了一个 chan string,用于在各个并发任务与主函数之间传递结果。
      • 发送(ch <- ...)和接收(<-ch)操作都是阻塞的,保证数据在通信过程中不会丢失或混乱。
  2. 并发函数fetch

    func fetch(url string, ch chan<- string) {start := time.Now()// 发起HTTP GET请求resp, err := http.Get(url)if err != nil {ch <- fmt.Sprint(err)         // 出错时,将错误信息发送到channel中return}// 使用 io.Copy 将响应体拷贝到 ioutil.Discard(垃圾桶),只关心字节数nbytes, err := io.Copy(ioutil.Discard, resp.Body)resp.Body.Close()                 // 关闭响应体,防止资源泄露if err != nil {ch <- fmt.Sprintf("while reading %s: %v", url, err)return}// 计算本次请求的耗时secs := time.Since(start).Seconds()// 将(耗时、字节数、URL)发送到channel中ch <- fmt.Sprintf("%.2fs  %7d  %s", secs, nbytes, url)}
    
    • ioutil.Discard:其实是一个实现了 io.Writer 接口的对象,它会丢弃写入的数据,相当于一个“黑洞”。这样做的目的是:我们只关心数据传输的字节数,而不需要保存数据本身。
    • 与一次性将所有数据读取到一个缓冲区相比,io.Copy 会采用分块(chunk)的方式读取数据,这样能有效降低内存使用,尤其是在响应体较大的情况下。
    • 将耗时、读取的字节数以及 URL 格式化为字符串,通过 channel 发送回主函数。这种方式使得各个并发任务的输出能在主函数中统一处理,避免多个 goroutine 同时输出导致的混乱。

语言特性

  1. goroutine 的并发执行
  • 每个 go fetch(url, ch) 都会在一个独立的执行流中运行,不会阻塞主函数。这意味着所有网络请求是同时进行的,程序总执行时间受限于最慢的请求,而不是所有请求的累加时间。
  1. channel 的阻塞特性
    • 发送阻塞:当一个 goroutine 试图发送数据到 channel 而没有接收者时,它会阻塞,直到有其他 goroutine 从 channel 接收数据。
    • 接收阻塞:同理,接收操作在 channel 为空时会阻塞,直到有数据可取。
    • 在本例中,主函数通过循环接收(<-ch)确保每个 fetch 的结果都被正确处理。这样既实现了任务同步,又避免了输出顺序混乱。
  2. 错误传递
    • 每个 fetch 中的错误都会通过 channel 传递到主函数,这种方式使得错误处理集中且易于管理

总结与反思

  • 并发执行实例

    指的是程序中可以同时运行的多个任务或执行单元。这些任务可以独立执行,共享程序的资源,并在某种程度上并行或交替运行。

  • goroutine

    是 Go 语言中用于实现并发执行的核心概念。它是一种轻量级的执行单元,由 Go 运行时调度管理,相比于传统的线程开销更低。每个 goroutine 都可以看作是一个并发执行实例,它们共同构成了程序的并发部分。

  • 每个通过 go 关键字启动的函数调用就是一个 goroutine,也就是一个并发执行实例。Go 语言利用 goroutine 提供了简单而高效的并发模型,让你可以轻松启动成百上千的并发任务,而不必担心传统线程所带来的高昂开销。


http://www.ppmy.cn/server/175643.html

相关文章

AIDD-人工智能药物设计-Nat. Biotechnol. | 绘制药物代谢扰动图谱,解码1520种药物的隐秘作用机制

Nat. Biotechnol. | 绘制药物代谢扰动图谱&#xff0c;解码1520种药物的隐秘作用机制 今天为大家介绍的是来自瑞士巴塞尔大学Mattia Zampieri团队的一篇论文。理解小分子的作用模式(mode of action&#xff0c;MoA)对于指导先导化合物的选择、优化和临床开发至关重要。在本研究…

C++和标准库速成(四)——逻辑比较运算符、三向比较运算符、函数和属性

目录 1. 逻辑比较运算符2. 三向比较运算符3. 函数3.1 函数的声明和调用3.2 函数返回类型的推断3.3 当前函数的名称3.4 函数重载 4. 属性4.1 [[nodiscard]]4.2 [[maybe_unused]]4.3 [[noreturn]]4.4 [[deprecated]]4.5 [[likely]]和[[unlikely]] 参考 1. 逻辑比较运算符 所有逻辑…

算法题刷题方法记录(蓝桥杯、Leetcode)

Algorithm exercises 尘封已久的算法&#xff0c;又要重新开始刷题了&#xff0c;不知道题量能不能达到预期 研一寒假期间&#xff0c;断断续续的&#xff0c;平均下来大概每天一题&#xff0c;懒懒散散的&#xff0c;开学来了继续刷。 记录下让人眼前一新的算法题 喜欢就要…

一个差劲的软件设计

项目概况&#xff1a; 之前自己设计并开发了一个用C#开发的上位机软件&#xff0c;整个软件只有一个Form&#xff0c;一个TabControl&#xff0c;3个TabControlPanel&#xff0c;总共100多个lable、textbox、ListBox等控件都放在这3个TabControlPanel里。 问题&#xff1a; 1.…

Day5 结构体、文字显示与GDT/IDT初始化

文章目录 1. harib02b用例&#xff08;使用结构体&#xff09;2. harib02c用例3. harib02d用例&#xff08;显示字符图案&#xff09;3. harib02e用例&#xff08;增加字符图案&#xff09;4. harib02g用例4.1 显示字符串4.2 显示变量值 5. harib02h用例&#xff08;显示鼠标&a…

TCP/IP四层网络模型

TCP/IP四层网络模型 TCP/IP四层网络模型OSI七层网络模型总结记忆描述 整理一下TCP/IP四层网络模型和OSI七层网络模型的知识点。 TCP/IP四层网络模型 TCP/IP模型是互联网的基础&#xff0c;它由以下四层组成&#xff1a; 应用层&#xff08;Application Layer&#xff09;&…

HTTP 和 HTTPS:从不安全到安全的蜕变之路

HTTP&#xff08;超文本传输协议&#xff09;和 HTTPS&#xff08;超文本传输安全协议&#xff09;是网络上最常用的协议&#xff0c;它们为网页浏览、数据传输提供基础支持。虽然只有一字之差&#xff0c;但 HTTPS 却对 HTTP 做出了巨大的改进&#xff0c;尤其在安全性方面。本…

VSTO(C#)Excel开发10:启动和卸载顺序 事件处理 监视变化

初级代码游戏的专栏介绍与文章目录-CSDN博客 我的github&#xff1a;codetoys&#xff0c;所有代码都将会位于ctfc库中。已经放入库中我会指出在库中的位置。 这些代码大部分以Linux为目标但部分代码是纯C的&#xff0c;可以在任何平台上使用。 源码指引&#xff1a;github源…