Go语言实现HTTP请求:net/http与gorequest实战示例

Ada
Ada
发布时间:2026-10-16 | 4人浏览过
原创

在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网络编程的资料请关注本站其它相关文章!

相关标签:

本站声明

本文内容仅供参考,不代表本站观点。转载或引用请注明出处。如发现内容问题,请通过联系我们页面反馈。

Python 相关产品和应用

全部下载

专题列表