📚 原创系列: “Go语言学习系列”
🔄 转载说明: 本文最初发布于"Gopher部落"微信公众号,经原作者授权转载。
🔗 关注原创: 欢迎扫描文末二维码,关注"Gopher部落"微信公众号获取第一手Go技术文章。
📑 Go语言学习系列导航
🚀 第二阶段:基础巩固篇本文是【Go语言学习系列】的第18篇,当前位于第二阶段(基础巩固篇)
- 13-包管理深入理解
- 14-标准库探索(一):io与文件操作
- 15-标准库探索(二):字符串处理
- 16-标准库探索(三):时间与日期
- 17-标准库探索(四):JSON处理
- 18-标准库探索(五):HTTP客户端 👈 当前位置
- 19-标准库探索(六):HTTP服务器
- 20-单元测试基础
- 21-基准测试与性能剖析入门
- 22-反射机制基础
- 23-Go中的面向对象编程
- 24-函数式编程在Go中的应用
- 25-context包详解
- 26-依赖注入与控制反转
- 27-第二阶段项目实战:RESTful API服务
📖 文章导读
在本文中,您将了解:
- Go语言HTTP客户端的基本使用方法
- 发送各种HTTP请求(GET、POST、PUT、DELETE等)
- 处理和解析HTTP响应
- 配置和优化HTTP客户端
- 文件上传与下载的实现
- HTTP客户端性能优化的最佳实践
Go语言的net/http包不仅提供了HTTP服务器功能,还包含了功能强大的HTTP客户端API,让我们能够轻松地与各种Web服务进行交互。本文将深入探讨这些API的使用方法,帮助您掌握在Go中构建高效可靠的HTTP客户端的技巧。
1. HTTP客户端基础
在Go中,net/http包提供了HTTP客户端和服务器实现。本文我们将重点介绍其客户端功能。
1.1 简单的GET请求
Go标准库使发送HTTP请求变得异常简单。以下是发送GET请求的基本方式:
package main
import (
"fmt"
"io"
"log"
"net/http"
)
func main() {
// 发送GET请求
resp, err := http.Get("https://api.github.com/users/golang")
if err != nil {
log.Fatalf("请求失败: %v", err)
}
defer resp.Body.Close() // 确保响应体被关闭
// 读取响应体
body, err := io.ReadAll(resp.Body)
if err != nil {
log.Fatalf("读取响应失败: %v", err)
}
// 打印状态码和响应体
fmt.Printf("状态码: %d\n", resp.StatusCode)
fmt.Printf("响应体: %s\n", body)
}
这个简单的例子展示了Go的HTTP客户端最基本的用法。让我们详细分析:
http.Get函数发送GET请求并返回响应和可能的错误- 使用
defer resp.Body.Close()确保资源被正确释放 io.ReadAll读取整个响应体- 可以通过
resp.StatusCode获取HTTP状态码
1.2 其他HTTP方法
除了GET,Go还支持所有标准HTTP方法:
// POST请求
resp, err := http.Post("https://httpbin.org/post", "application/json",
strings.NewReader(`{"name":"gopher","message":"hello"}`))
// PUT请求
req, err := http.NewRequest(http.MethodPut, "https://httpbin.org/put",
strings.NewReader(`{"name":"gopher","status":"updated"}`))
client := &http.Client{
}
resp, err := client.Do(req)
// DELETE请求
req, err := http.NewRequest(http.MethodDelete, "https://httpbin.org/delete?id=123", nil)
resp, err := client.Do(req)
1.3 请求头与请求参数
设置请求头和URL参数是常见需求:
// 创建请求
req, err := http.NewRequest("GET", "https://api.example.com/users", nil)
if err != nil {
log.Fatal(err)
}
// 添加请求头
req.Header.Add("Authorization", "Bearer token123456")
req.Header.Add("Content-Type", "application/json")
req.Header.Add("User-Agent", "GoHTTPClient/1.0")
// 添加URL参数
q := req.URL.Query()
q.Add("page", "1")
q.Add("limit", "10")
q.Add("sort", "created_at")
req.URL.RawQuery = q.Encode()
// 发送请求
client := &http.Client{
}
resp, err := client.Do(req)
// ...处理响应
2. 处理HTTP响应
2.1 读取响应体
处理HTTP响应的核心是正确读取响应体。前面我们已经看到了使用io.ReadAll的方式,但还有其他模式:
// 分块读取大型响应
resp, err := http.Get("https://example.com/large-file")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
// 使用缓冲读取
buf := make([]byte, 1024)
for {
n, err := resp.Body.Read(buf)
if err == io.EOF {
break // 读取完成
}
if err != nil {
log.Fatal(err)
}
// 处理读取的部分数据
fmt.Printf("读取了 %d 字节的数据\n", n)
fmt.Printf("数据片段: %s\n", buf[:n])
}
对于结构化数据(如JSON),可以直接解码:
// 解码JSON响应
resp, err := http.Get("https://api.github.com/users/golang")
if err != nil {
log.Fatal(err)
}
defer resp.Body.Close()
var user struct {
Login string `json:"login"`
ID int `json:"id"`
Name string `json:"name"`
Bio string `json:"bio"`
Public struct {
Repos int `json:"public_repos"`
} `json:"public_repos"`
}
if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
log.Fatal(err)
}
fmt.Printf("用户信息: %+v\n", user)
2.2 处理状态码
HTTP响应的状态码表明请求的结果:
resp, err := http.

最低0.47元/天 解锁文章
2154

被折叠的 条评论
为什么被折叠?



