【Go语言圣经1.5】

【Go语言圣经】从零开始学Go----1.入门篇 《Go语言圣经》读书笔记,完整知识点整理,从零开始学Golang 阅读详情

目标

概念

要点(案例)

实现了一个简单的 HTTP 客户端程序,主要功能是:

  • 读取命令行参数:程序从命令行获取一个或多个 URL。
  • 发送 HTTP GET 请求:使用 Go 内置的 net/http 包,通过 http.Get 函数向每个 URL 发送请求。
  • 读取并输出响应内容:利用 io.ReadAll 读取服务器返回的响应体,将其作为字符串输出到标准输出(屏幕)。
  • 错误处理:如果请求过程中出现错误,程序会在标准错误输出(os.Stderr)中打印错误信息,并以错误状态码退出程序。

这段代码的设计思路与 Unix 下的 curl 工具有相似之处,展示了如何用 Go 编写一个最简单的 HTTP 请求工具。

  1. 包导入

    // Fetch prints the content found at a URL.
    package main
    
    import (
        "fmt"
        "io/ioutil"
        "net/http" // 实现了 HTTP 客户端和服务端的基本功能,这里主要用来发起 GET 请求。
        "os"
    )
    
  2. 程序入口和获取命令行参数

    func main() {
        for _, url := range os.Args[1:] {
            // ...
        }
    }
    
    
  3. 发起 HTTP GET 请求

    resp, err := http.Get(url)
    if err != nil {
        fmt.Fprintf(os.Stderr, "fetch: %v\n", err)
        os.Exit(1)
    }
    
    • 使用 fmt.Fprintf 将错误信息写入标准错误流,并通过 os.Exit(1) 退出程序,状态码 1 表示出现错误。
  4. 读取响应体

    b, err := io.ReadAll(resp.Body)
    resp.Body.Close()
    if err != nil {
        fmt.Fprintf(os.Stderr, "fetch: reading %s: %v\n", url, err)
        os.Exit(1)
    }
    
    
    • 服务器返回的响应体是一个流
    • 用io.ReadAll全部读取出来,并存入变量 b 中。
      • b 是由 io.ReadAll 返回的一个 []byte,它用来存储从 resp.Body 中读取到的所有数据。从这个角度看,b 就充当了一个缓冲区,其主要特点和作用如下:
        • 当你调用 io.ReadAll(resp.Body) 时,Go 语言会从网络流(resp.Body)中一次性读取所有数据,并将这些数据存储到一个新的切片 b 中。
        • 这个切片 b 就起到了“缓冲”的作用:它暂时保存了从网络中读取到的数据,方便程序后续操作(比如打印到标准输出)。
        • 为了存储数据,程序必须从操作系统申请一块内存区域,这就是“申请缓冲区”。在这里,io.ReadAll 内部会动态分配足够大小的内存来保存整个响应体的数据。
    • 关闭响应体:调用 resp.Body.Close() 释放与响应相关的资源,防止内存或文件描述符泄露。
    • 很多程序会使用 defer resp.Body.Close() 来确保函数退出时自动关闭流,这也是 Go 中的一个重要惯用法。
      • 在更多场景下推荐使用 defer 来保证资源释放,即使函数中途发生错误也能正确关闭资源。
  5. 输出结果

    fmt.Printf("%s", b)
    

语言特性

  1. 检查错误:Go 语言没有异常机制,而是通过返回值来处理错误。每一步操作(如 HTTP 请求、读取流)都需要检查错误,这种显式的错误处理方式有助于写出健壮的代码。
  2. 资源管理:及时释放资源:读取完响应体后调用 resp.Body.Close() 是非常重要的,防止资源泄露。理解这点对于编写网络或文件 I/O 程序尤为关键。
  3. 标准库的强大支持
    • net/http 包:Go 语言的标准库提供了对 HTTP 的强大支持,不仅能发起请求,还可以构建服务器,这让开发者能快速实现网络应用。
    • io 包:提供了对 I/O 操作的统一抽象,如 io.ReadAll 能简化从流中读取数据的操作。

总结

  1. 这段代码是串行处理每个 URL,但 Go 内置的并发机制(goroutine、channel)可以很方便地改造此程序
  2. 为何在操作结束后需要关闭流(I/O流:文件流,网络流)
    • 操作系统为每个进程分配的文件描述符和网络连接数量是有限的。如果程序中频繁打开流而不关闭,长时间运行后会耗尽这些资源,导致后续无法打开新的文件或建立新的网络连接。
    • 不及时关闭流会导致资源泄露(Resource Leak),即占用的内存和其他系统资源不能被其他部分程序或其他程序使用。这种泄露会降低程序的性能,甚至引发系统崩溃或不稳定。
    • 某些流在写操作时会进行缓冲,如果不调用关闭操作,缓冲区中的数据可能没有及时刷新到磁盘或发送到网络端,可能破坏数据完整性。通过关闭流,系统会自动刷新缓冲区,确保所有数据都已经正确写入或传输。
    • 文件在打开时可能被操作系统或其他程序加锁,防止数据被同时修改。关闭文件流可以释放这些锁定,使其他进程能够正常访问文件,保障系统的安全性和数据的一致性。
  3. 缓冲区
    • 定义:在程序设计中,缓冲区是一个抽象概念,用来描述数据暂存的位置。它帮助平滑数据流的传输,比如在从磁盘读取数据或向网络发送数据时,不必每次都进行低效的逐字节操作,而是先把数据存入缓冲区,再统一处理。

题目

练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout,避免申请一个缓冲区(例子中的b)来存储。记得处理io.Copy返回结果中的错误。

// 使用 io.Copy 将响应体直接写入标准输出,避免申请额外的缓冲区
_, err = io.Copy(os.Stdout, resp.Body)
  • 调用 io.Copy 函数,将数据从 src(这里是 resp.Body)流式复制到 dst(这里是 os.Stdout)
    • io.Copy 的工作原理是创建一个固定大小(比如32KB)的缓冲区,在循环中不断地从源(src)读取一块数据,然后立即写入目标(dst)。这样,只需要维持这块缓冲区的内存,而不必为整个数据内容分配一大块连续内存区域。
    • 分块,chunk
  • 对于大文件或长响应数据,直接拷贝可以减少内存占用。流式处理:不需要一次性把所有数据加载到内存中,有助于处理大数据流。

练习 1.8: 修改fetch这个范例,如果输入的url参数没有 http:// 前缀的话,为这个url加上该前缀。你可能会用到strings.HasPrefix这个函数。

  	// 如果 URL 没有 "http://" 前缀,则自动添加
		if !strings.HasPrefix(url, "http://") {
			url = "http://" + url
		}

练习 1.9: 修改fetch打印出HTTP协议的状态码,可以从resp.Status变量得到该状态码。

// 打印出 HTTP 协议的状态码
fmt.Fprintf(os.Stdout, "HTTP status: %s\n", resp.Status)

Go语言圣经练习5.1-5.4 前言 网上找不到5.1的解答参考,所以只能手动写了一个。仅供参考。 题目 修改findlinks代码中遍历n.FirstChild链表的部分,将循环调用visit,改成递归调用。 代码 package main import ( "fmt" "os" "golang.org/x/net/html" ) func main() { doc, err := html.Parse(os.St... 阅读详情

相关推荐

Go语言圣经 - 第1章 入门 - 1.5 & 1.6 & 1.7 & 1.8 获取URL & 并发获取多个URL & Web服务 & 本章要点

第1章 入门 1.5 获取Url 1.编写代码 Go语言提供了net 包以及其它包,以便我们可以用来构建我们访问网络资源的程序,我们来看一个例子 package main import ( "fmt" "io/ioutil" "net/http" "os" ) func main() { for _,url := range os.Args[1:]{ resp,err:=http.Get(url) if err!=nil{ fmt.Fprintf(os.Stderr,"fetch:

weixin_51487151的博客 335

Go语言圣经

第一章入门

kwdecsdn的博客 2756

Android开发者必看:5分钟搞定DeepSeek API接入(附完整代码示例)

本文为Android开发者提供快速接入DeepSeek API的完整指南,包含环境配置、网络层设计、请求体构建等关键步骤,并附有详细代码示例。通过工程化实践,帮助开发者高效集成AI对话、代码生成等高级功能,提升移动应用竞争力。

bush的博客 535

Go语言圣经总结

如果没有足够的增长空间的话,appendInt函数则会先分配一个足够大(2*len(old_slice),这个扩容算法因不同语言不同)的slice用于保存新的结果,先将输入的x复制到新的空间,然后添加y元素。当调用一个函数的时候,函数的每个调用参数将会被赋值给函数内部的参数变量,所以函数参数变量接收的是一个复制的副本,并不是原始调用的变量。因为函数参数传递的机制导致传递大的数组类型将是低效的,并且对数组参数的任何的修改都是发生在复制的数组上,并不能直接修改调用时原始的数组变量。

yelvens的博客 2058

从0到1:提示工程架构师搭建Agentic AI系统的全流程实战手册

Agentic AI(自主智能体)是具备自主决策能力的大模型应用感知(Perceive):获取外部环境信息(比如代码仓库、用户输入、数据库数据);记忆(Memory):存储和检索历史信息(比如过去的审计记录、用户偏好);规划(Plan):将复杂任务拆解为可执行的步骤(比如“代码审计”拆成3步);行动(Act):调用工具或API完成具体操作(比如调用Git克隆仓库、调用Safety查漏洞);反馈(Feedback):根据结果调整策略(比如用户说“报告不够详细”,下次增加逻辑漏洞的分析深度)。

AI Agent Harness Engineering 1042

大模型辅助意图识别,更懂你的客户洞察平台

通过大量的学习和训练,大模型不仅具备庞大的知识库,更掌握着丰富的语言模式和语义规则,能够精准地理解每一段对话的含义,为每一通对话进行全面、准确的标注。主要来自客户的行为信息,将客户与机构的重要时刻以时间轴的方式呈现出来,掌握客户生命周期的完整脉络,识别一些容易被忽略的重要营销MOT(Moment Of Truth,关键时刻研究)机会,提示理财经理跟进处理。将客户的历史交易数据和埋点系统采集的客户行为数据结合起来,辅以部分内容资讯的偏好探测,综合分析和预测客户在各个维度的喜好程度,实现千人千面的客户推送。

Dezhuzhineng的博客 2159

Go语言圣经(中文版)

http://golang-china.github.io/gopl-zh/index.html

dazheng 1万+

Excel-MCP实战指南:零代码实现大模型与Excel的智能交互

本文详细介绍了Excel-MCP工具如何实现大模型与Excel的无缝交互,无需编写代码即可完成数据读写、图表生成等复杂操作。通过实战案例展示了Excel-MCP在销售报表自动化、财务对账等企业级场景中的应用,大幅提升工作效率。文章还提供了安装指南、核心功能解析和常见问题解决方案。

weixin_29212429的博客 433

GO语言从入门到达人--GO语言圣经--入门

1.Go的一些基本规范 GO是编译型语言。Go的工具链讲程序的源文件转变为机器相关的原生二进制 GO原生地支持Unicode,支持任何国家的语言。 GO语言其实由三部分组成 : 1.声明自己属于哪个包 package main 2.导入其他包 import (“fmt”) 3.程序本身 func main(){ 代码块 } 一般import后面是组成函数 – func 函数 const 常量 var 变量 type 类型 GO语言不适用分号进行结尾。 GO语言的" { "是不可以单独一行的,必须与f

weixin_44324366的博客 671

避开PFC设计大坑:从环路分析到参数整定的5个常见误区与解决方案

本文深入解析PFC电路设计中从环路分析到参数整定的5个常见误区,包括电感参数设计、小信号模型适用边界、电压环与电流环耦合效应等。通过实际案例和PSIM仿真数据,提供工程落地的解决方案,帮助工程师避开设计陷阱,提升电路性能与可靠性。

weixin_30666401的博客 325

AI工具 | 每个打工人必备的15款人工智能超级工具

不过,还是有一些靠谱的人工智能平台,它们可不只是营销噱头。有些AI公司正试图改变游戏规则。人工智能工具让人们能够更聪明地工作,而不是更辛苦地劳作。如果你想知道未来有什么,那就来看看这10款人工智能工具吧,它们将彻底改变我们的工作方式。

Vampire_2017的博客 5万+

【Go语言圣经5.1】

标准写法特点:明确地声明了参数和返回值,返回值直接在return语句中指定。命名返回值z = x - yreturn // 此处返回 z 的值特点:返回值z在函数体内被视作一个局部变量,函数结束时自动返回其值。使用空白标识符return x特点:使用忽略第二个参数,表示它不会在函数体内使用。省略参数名return 0特点:即使没有为参数命名,函数签名仍然明确为,但函数体内无法访问这些参数值。

Pyroyster的博客 1004

系统架构设计(以飞控系统、航电系统、机电管理系统、电子电气架构为例)

系统架构涉及对系统的结构和行为进行高层次的描述。它包括系统的组成部分、这些部分之间的关系、与外部环境的交互方式,以及满足特定功能和非功能性需求的方法。系统架构定义了系统的总体设计蓝图,指导系统的开发、集成、部署和维护。系统架构设计的目的是通过合理的结构和设计原则,确保系统能够高效、稳定、安全地运行,满足当前和未来的需求,同时具备良好的维护性、扩展性和可持续性。良好的系统架构不仅能够提高系统的开发效率和运行性能,还能降低长期的维护和运营成本,支持系统的持续演进和技术更新。

qq_41854911的博客 3052

Go语言圣经练习6.1~6.5

前言 位运算操作比较多,练练手。 代码分两块 一个是代码部分,另一个是测试代码部分。使用 go test xxx 返回ok即正确。 题目: 练习6.1: 为bit数组实现Len, Remove, Copy, Clear 练习 6.2: 定义一个变参方法(*IntSet).AddAll(…int),这个方法可以为一组IntSet值求和,比如 s.AddAll(1,2,3)。 练习6.3:并集、差集、...

u014472777的专栏 342

【异常】OpenClaw LLM请求超时故障全链路排查与解决方案 LLM request timed out. 网络连接超时了

摘要: OpenClaw LLM请求超时故障是高频网络交互问题,表现为客户端在预设时间内未收到服务端响应。根因分为四类:客户端配置缺陷(如超时阈值不合理)、网络链路异常(防火墙拦截等)、服务端问题(限流/宕机)及硬件瓶颈(算力不足)。解决方案分三步: 通用排查:检查网络连通性、关闭防火墙/代理校验,调整超时阈值至60-300秒; 分场景修复:云端API需核对密钥/限流规则,本地部署需验证服务状态与硬件资源; 兜底方案:重启程序、更新版本或更换服务端点,结合日志精准定位。修复后不影响OpenClaw数据完整性

奶爸的编程之路,也就一周冷个三天 2058

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

Go语言圣经 - 习题 - 1.5. 获取URL

package main import ( "fmt" "io" "io/ioutil" "net/http" "os" "strings" ) func main() { for _, url := range os.Args[1:] { if !strings.HasPrefix(url, "http://") {

Hello World 1463

锂电池充电器电路设计 里面有电路

锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。

Go语言圣经 - 第5章 函数 - 5.1 函数的声明 & 5.2 递归

第5章 函数 函数可以让我们将一个语句序列打包成一个单元,然后可以从程序中其他地方多次调用,函数的机制可以让我们把一个大的工作分解成小任务。前面我们已经接触过函数,本章我们将讨论函数的更多特性 5.1 函数的声明 函数的声明包括函数名、形式参数列表、返回值列表(可省略)以及函数体 func name(parameter-list)(result-list) { body } 形式参数列表包含参数名称和参数类型,它们是局部变量,由参数调用者提供。返回值列表包含了返回值的变量名称和类型,如果函数没有返

weixin_51487151的博客 291

老版QQ原生表情gif动态

这是老版的QQ表情,不过全是动态的的,Windows照片查看器是不会动的,可以右击用浏览器打开查看,再说一遍是老版的,只是分享给宁愿用老版也要动态的人。

IMSL CNL 7.0.0 (x86-64)Crack

IMSL CNL 7.0.0 (x86-64)Crack intel的算法库破解文件,这是C++版本的破解文件

Go语言圣经习题练习_1.5. 获取URL

练习 1.7: 函数调用io.Copy(dst, src)会从src中读取内容,并将读到的结果写入到dst中,使用这个函数替代掉例子中的ioutil.ReadAll来拷贝响应结构体到os.Stdout,避免申请一个缓冲区(例子中的b)来存储。记得处理io.Copy返回结果中的错误。 func main() { for _,url := range os.Args[1:] { ...

weixin_30312557的博客 258

想系统学习GO语言(Golang

作者:知乎用户 链接:https://www.zhihu.com/question/30461290/answer/210414739 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 学习任何一门语言,都要学习好基础,把基础打牢,那些框架对你来说都是工具,你自己的基础好,懂得了他们的原理,自己就可以创造更优秀的框架。基础推荐官方文档,没有什么比这个更清晰了。官方文...

437

go资料

作者:知乎用户 链接:https://www.zhihu.com/question/30461290/answer/210414739 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 学习任何一门语言,都要学习好基础,把基础打牢,那些框架对你来说都是工具,你自己的基础好,懂得了他们的原理,自己就可以创造更优秀的框架。 基础推荐官方文档,没有什么比这个更清晰...

百雨的博客 392

想系统学习GO语言(Golang)

作者:飞雪无情 链接:https://www.zhihu.com/question/30461290/answer/210414739 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。 学习任何一门语言,都要学习好基础,把基础打牢,那些框架对你来说都是工具,你自己的基础好,懂得了他们的原理,自己就可以创造更优秀的框架。 基础推荐官方文档,没有什么比这个更清晰...

bujidexinq的专栏 347

go学习资料

go书单 1.代码规范 https://github.com/golang/go/wiki/CodeReviewComments 2.基础知识 先看: https://github.com/mikeluwen/build-web-application-with-golang/blob/master/zh/preface.md 参考官方文档: https://go-zh.o...

aokedlpxv22775032的博客 102

[日常] Go语言圣经-函数递归习题

练习 5.1: 修改findlinks代码中遍历n.FirstChild链表的部分,将循环调用visit,改成递归调用。 练习 5.2: 编写函数,记录在HTML树中出现的同名元素的次数。 练习 5.3: 编写函数输出所有text结点的内容。注意不要访问<script>和<style>元素,因为这些元素对浏览者是不可见的。 练习 5.4: 扩展visit函数,使其能够...

weixin_34049032的博客 280

【Go语言圣经3.1】

你有一个数字钟表,比如钟表上标有数字0到11。当你往前走时,比如从10走2步,就会变成0。两的补码就利用了这种“绕圈”的特性,把数字“绕回来”来表示负数。“两的补码”这个名字来源于它表示负数的方法:在二进制中,用一种方法把一个正数变成它的负数,而这个方法实际上就是用“2的幂”来做补数。因为2^n的基础是2,所以这种方法叫做两的补码。假设我们用8位二进制来表示数字,负数的表示其实就是“2^8减去正数”。比如-5此时是256-5。

Pyroyster的博客 794

Go学习圣经:0基础精通GO开发与高并发架构(1)

从Java高薪岗位和就业岗位来看,云原生、K8S、GO 现在对于 高级工程师/架构师来说,越来越重要。尼恩从架构师视角出发,基于自己的尼恩 3高架构师知识体系和知识宇宙,写一本《GO学习圣经》。

架构师尼恩 4753

go语言圣经读书笔记(上)

总而言之,go总结了很多厉害语言经验,由大佬们组队创造的,如图。

weixin_56551472的博客 1972
上一篇: 【LeetCode110】平衡二叉树
下一篇: 【go语言圣经1.6】
Pyroyster
博客等级 码龄7年 206粉丝 55原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值