Go语言实现HTTP请求:net/http与gorequest实战示例
在Go语言开发中,HTTP客户端是数据交互的基础设施。本文总结并演示了三种主流方案:基础的http.Post、支持完整控制的http.NewRequest以及语法糖丰富的第三方库gorequest。内容涵盖JSON序列化、Header设置、响应读取及错误处理,帮助开发者在不同场景下选择最优解。
使用 http.Post 发起基础POST请求
net/http包提供了极简的http.Post方法,适用于不需要配置复杂Header或查询参数的场景。该方法内部会自动实例化Client并发送请求。
适用场景:表单提交(x-www-form-urlencoded)或简单的纯文本POST。
import (
"fmt"
"net/http"
"net/url"
"strings"
)
func ExampleSimplePost() {
// 1. 构造表单数据
data := url.Values{"start": {"100"}, "hobby": {"xxxx"}}
body := strings.NewReader(data.Encode())
// 2. 直接发送请求
resp, err := http.Post("http://127.0.0.1:9338", "application/x-www-form-urlencoded", body)
if err != nil {
fmt.Println("Request failed:", err)
return
}
defer resp.Body.Close()
}使用 http.NewRequest 进行精细化控制
当需要添加自定义Header(如认证Token、特定Content-Type)、处理Cookie或复用Transport时,必须使用http.NewRequest配合http.Client。http.Post等快捷方法无法传入自定义Header。
第1步:准备请求体与结构体定义
首先需要定义用于序列化的结构体,并将数据转换为JSON格式作为Body。注意Go中的结构体字段需首字母大写以暴露给编码/解码器。
import (
"bytes"
"encoding/json"
"fmt"
"io/ioutil"
"net/http"
)
// 注意:JSON标签用于指定输出的键名
type StudentReq struct {
ID string `json:"id"`
Name string `json:"name"`
}
func main() {
stu := StudentReq{
ID: "2ed4tg5fe35fgty3yy6uh",
Name: "amber",
}第2步:序列化并创建Request对象
使用json.Marshal将结构体转为字节流,并通过bytes.NewReader包装为Reader供请求使用。随后创建Request对象并设置必要的Header。
// 序列化
stuData, marshalErr := json.Marshal(&stu)
if marshalErr != nil {
fmt.Println("Marshal error:", marshalErr)
return
}
reader := bytes.NewReader(stuData)
// 创建请求
request, newErr := http.NewRequest("POST", "http://192.168.1.12:8000/create", reader)
if newErr != nil {
fmt.Println("NewRequest error:", newErr)
return
}
// 设置Header
// 注意:Key必须严格区分大小写,应为 Content-Type 而非 ContentType
request.Header.Set("Content-Type", "application/json")第3步:执行请求并处理响应
实例化http.Client并调用Do方法发送请求。务必确保在ioutil.ReadAll完成之后才关闭Body,否则会导致“read on closed response body”错误。建议使用defer在函数退出时自动清理资源。
client := &http.Client{}
response, doErr := client.Do(request)
if doErr != nil {
fmt.Println("Client Do error:", doErr)
return
}
// 延迟关闭Body,防止资源泄露
defer response.Body.Close()
// 读取Body
bodyBytes, readErr := ioutil.ReadAll(response.Body)
if readErr != nil {
fmt.Println("ReadAll error:", readErr)
return
}
fmt.Printf("Response Body: %s\n", string(bodyBytes))
// 反序列化响应
var stuReq StudentReq
unmarshalErr := json.Unmarshal(bodyBytes, &stuReq)
if unmarshalErr != nil {
fmt.Println("Unmarshal error:", unmarshalErr)
return
}
fmt.Println(json.MarshalIndent(stuReq, "", " "))
}关键注意事项
- Header键名规范:HTTP Header键名对大小写敏感但不严格区分,但在Go的
header.Set()中建议遵循标准格式(如Content-Type),避免写成ContentType。 - 生命周期管理:如果请求逻辑跨越多层函数,务必手动传递Response或在最外层统一Deferred Close。在多层嵌套中过早关闭Body会引发panic或IO错误。
- 内存泄漏风险:即使请求失败,若未正确读取Body或关闭连接,可能导致TCP连接无法复用或泄露。
使用 gorequest 简化调用流程
gorequest是一个流行的Go HTTP封装库,链式调用风格显著减少了样板代码。它特别适合需要在URL中拼接大量Query Parameter的场景。
优势:自动处理状态码检查、错误聚合、JSON序列化与解析。
import (
"encoding/json"
"github.com/parnurzeal/gorequest"
"log"
)
func ExampleGorequest() {
resp, body, errs := gorequest.New().
Post("http://127.0.0.1/create").
Param("ip", "192.168.1.4").
EndBytes()
// 检查是否有错误(包括网络错误和HTTP状态码错误)
if errs != nil || resp.StatusCode >= 300 {
log.Errorf("fail to call api with errors %v, body %+v", errs, body)
return
}
var stuReq StudentReq
if unErr := json.Unmarshal(body, &stuReq); unErr != nil {
log.Println("Unmarshal failed:", unErr)
return
}
fmt.Println(json.MarshalIndent(stuReq, "", " "))
}以上就是Go语言实现HTTP请求(NewRequest/gorequest)的详细内容,更多关于Go网络编程的资料请关注本站其它相关文章!
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









