Learn HTTP Clients in Go(Boot.dev)
Boot.dev HTTP 客户端课程的个人学习记录:JSON、URL、请求头、方法以及传输错误与 HTTP 状态的区别。
Learn HTTP Clients in Go(Boot.dev)
[!info] related notes
- 所属路线:Go Web 与后端 · Go 标准库与应用
- 来源平台:Boot.dev
- 依赖前置:boot-dev-learn-http-protocol-in-go · net/http
- 后续课程:boot-dev-learn-http-servers-in-go
概览
boot.dev 上的 learn http clients in go 课程 主要记录 Go 作为客户端时需要掌握的知识;不是课程完整大纲或完成证明。
why http
这一章节讲了大致下面内容:
- 本课场景通过 HTTP 获取数据;
net/http的响应体是io.ReadCloser字节流,读取后可得到[]byte,也可直接解码。 - 基础的 front-end、back-end、client、server、URL、http等的概念
- go 一般使用自带的 net/http 标准库来进行请求
JSON
- 讲了 JSON定义
encoding/json可对字节切片进行 Marshal/Unmarshal,也可用 Decoder/Encoder 处理 Reader/Writer。下面是处理响应的函数内片段,假定已定义Issue、检查请求错误与状态码,并安排响应体关闭。
var issues []Issue // 定义一个 issues
decoder := json.NewDecoder(res.Body) // 创建解码器
if err := decoder.Decode(&issues); err != nil { // 解码器填充 issues
fmt.Println("error decoding response body")
return nil, fmt.Errorf("decode response body: %w", err)
}
json.Unmarshal 处理完整的 JSON 字节切片。以下对比片段只适用于响应大小已有可信上界的场景;对任意远端响应直接 io.ReadAll 会无界占用内存。
// res is an http.Response
defer res.Body.Close()
data, err := io.ReadAll(res.Body)
if err != nil {
return nil, err
}
var issues []Issue
if err := json.Unmarshal(data, &issues); err != nil {
return nil, err
}
json.Marshalgo struct 转为 JSON 数据map[string]any可表示动态 JSON 对象;默认解码到接口时数字成为float64。稳定结构优先用类型明确的 struct,需要保留数字文本时考虑Decoder.UseNumber()。
单次 Decode 只消费一个 JSON 值,不证明后面没有其他数据。接口要求整个响应只能有一个值时,还需确认后续为 EOF,见 JSON 与序列化。
URL 解析与 DNS 的区别
net/url 解析 URL 的组成部分,不进行 DNS 查询。Hostname() 只是取出主机名;DNS 地址解析是另一项工作,见 URL 和 DNS。
parsedURL, err := url.Parse("https://homestarrunner.com/toons")
if err != nil {
fmt.Println("error parsing url:", err)
return
}
parsedURL.Hostname()
// homestarrunner.com
URIs
URI 是统一资源标识符(Uniform Resource Identifier);URL 是统一资源定位符(Uniform Resource Locator)。URI 可以具有定位、命名或两者兼有的作用,不能把 URL 和 URN 简化为互斥且穷尽的两类。
URL struct
http://testuser:testpass@testdomain.com:8080/testpath?testsearch=testvalue#testhash
以下 ParsedURL 是课程练习自定义结构,不是标准库 url.URL 的字段定义;示例用户名和密码仅用于拆解格式:
return ParsedURL{
protocol: "http",
username: "testuser",
password: "testpass",
hostname: "testdomain.com",
port: "8080",
pathname: "/testpath",
search: "testsearch=testvalue",
hash: "testhash",
}
Use these fields and methods of the URL struct:
SchemeUser.Username()User.Password()- this method returns two values: the password if set and whether it was setHostname()Port()PathRawQueryFragment
Scheme 如 http、https、ftp、mailto;并非每种 scheme 都对应网络协议,也并非都需要 //,例如 mailto:noreply@jello.app。URL fragment 通常不随 HTTP 请求发送给服务器。
headers
请求头
主要记录创建请求、设置请求头和读取响应头。下面是函数内片段,需导入 fmt、net/http、time;实际应用可复用带超时的 Client。
// creating a new request
req, err := http.NewRequest("GET", "https://api.example.com/users", nil)
if err != nil {
fmt.Println("error creating request: ", err)
return
}
// setting a header on the new request
req.Header.Set("Accept", "application/json")
// making the request
client := http.Client{Timeout: 10 * time.Second}
res, err := client.Do(req)
if err != nil {
fmt.Println("error making request: ", err)
return
}
defer res.Body.Close()
// reading a header from the response
header := res.Header.Get("last-modified")
fmt.Println("last modified: ", header)
// 只修改本地响应对象中的 Header,不影响服务器或已完成的网络传输
res.Header.Del("last-modified")
请求头可携带认证信息,也用于内容协商、缓存条件等;收到响应后应检查 res.StatusCode,不能只检查 err。
Method
put,post,delete,patch,get 等语义方法
error
在实际的网络开发中,发起请求并不总是顺畅无阻的。背后的核心知识点可以分为以下两大部分:
1. 请求执行错误
这类错误表示客户端没有完成预期的请求流程,可能发生在发送前,也可能发生在服务端已经执行操作之后。超时不能证明请求未到达,重试写操作需考虑幂等性。
- 原因:URL 无效、DNS 失败、连接或读取超时、TLS/协议问题,也可能是客户端重定向策略拒绝。
- Go 中的表现:调用
http.Get(url)会直接返回一个非空的err。 - 处理逻辑:先处理
err,不要假设res非空。标准 Client 因 CheckRedirect 失败可能同时返回 response 和 error,但该响应体已关闭;不要把“HTTP 状态码 0”当作服务器返回值。
2. HTTP 非成功状态
这类错误发生在网络连接正常建立,并且服务器也成功返回了 HTTP 响应,但返回的状态码指示请求出了问题。
- 原因:例如请求的资源不存在(
404 Not Found)、未授权访问(401 Unauthorized)、服务器内部报错(500 Internal Server Error)等。 - Go 中的表现:
http.Get(url)返回的err为nil,因为从网络协议角度来看通信是成功的。但是响应对象res中的StatusCode字段会反应具体的状态(如 404、500 等)。 - 处理逻辑:我们需要手动检查状态码。一般情况下,只有
200到299范围内的状态码(如http.StatusOK即 200)表示 HTTP 层成功;业务结果仍需按接口契约校验,204 也不应强行解码 JSON。如果不是200系列,我们需要根据res.StatusCode或res.Status(状态文本)单独进行错误处理,并记得关闭响应体defer res.Body.Close()。
待继续学习
- Path 与 HTTPS:原记录尚未展开。
curl用于发起请求与检查响应,jq用于处理 JSON。
核对依据
2026-10-06 按标准库核对技术内容;课程站访问返回 403,未据此推断课程下架或变更个人学习状态。