golang的http客户端封装

简介

net/http 是 Go 语言标准库的一部分,它提供了创建 HTTP 客户端和服务器的能力。这个包通过简化与 HTTP 协议的交互,让开发者能够方便地构建 HTTP 请求和响应,以及处理路由等任务。

本文以 net/http 包作为底层,封装一个包含 get , post , form-data 请求的工具包

开始

创建一个项目 demo ,并创建以下目录:

GET方法

在 client 文件中创建如下方法

go 复制代码
package client

import (
	"bytes"
	"crypto/tls"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"time"
)

/***
url 请求地址
header 头部
requestData 请求数据
*/
func GET(path string,header map[string]string, requestData map[string]string) []byte  {
	if(len(requestData) >0){
		params := url.Values{}
		for k,v:=range requestData{
			params.Add(k,v)
		}
		path = path + "?" + params.Encode()
	}
	req, _ := http.NewRequest("GET", path, bytes.NewBuffer([]byte("")))
	req.Header.Set("cache-control", "no-cache")
	for key,value :=range header{
		req.Header.Set(key, value)
	}
	//过滤https证书
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		//关闭连接池,不然会打满语句柄
		DisableKeepAlives: true,
	}

	//设置请求超时时间为20秒
	client := &http.Client{
		Transport: tr,
		Timeout: 20 * time.Second,
	}
	res, err := client.Do(req)
	if res !=nil{
		defer res.Body.Close()
		body, _ := ioutil.ReadAll(res.Body)
		return body
	}
	if err !=nil {
		fmt.Printf("请求错误: %s\n", err.Error())
		return nil
	}
	return nil
}

注意:此处需要关闭连接池,不然在多携程异步调用的时候,由于请求过多,会出现语句饼打满,导致请求报错的情况。

POST

go 复制代码
/***
url 请求地址
header 头部
requestData 请求数据,json数据
*/
func POST(path string,header map[string]string, requestData []byte) []byte  {
	req, _ := http.NewRequest("POST", path, bytes.NewBuffer(requestData))
	req.Header.Set("cache-control", "no-cache")
	_, ok := header["content-type"]
	if ok ==false {
		req.Header.Set("content-type", "application/json")
	}
	for key,value :=range header{
		req.Header.Set(key, value)
	}
	//过滤https证书
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		//关闭连接池,不然会打满语句柄
		DisableKeepAlives: true,
	}

	//设置请求超时时间为20秒
	client := &http.Client{
		Transport: tr,
		Timeout: 20 * time.Second,
	}
	res, err := client.Do(req)
	if res !=nil{
		defer res.Body.Close()
		body, _ := ioutil.ReadAll(res.Body)
		return body
	}
	if err !=nil {
		fmt.Printf("请求错误: %s\n", err.Error())
		return nil
	}
	return nil
}

FormData

go 复制代码
/***
url 请求地址
header 头部
params 其他请求参数
paramName 文件名称
path 本地文件路径
*/
func FormData(url string,header map[string]string,params map[string]string, paramName, path string) []byte {
	file, err := os.Open(path)
	if err != nil {
		fmt.Printf("打开文件错误: %s\n", err.Error())
		return nil
	}
	defer file.Close()

	body := &bytes.Buffer{}
	writer := multipart.NewWriter(body)
	//fmt.Printf("请求参数:%+v",params)
	part, err := writer.CreateFormFile(paramName, filepath.Base(path))
	if err != nil {
		fmt.Printf("文件错误: %s\n", err.Error())
		return nil
	}
	_, err = io.Copy(part, file)

	for key, val := range params {
		_ = writer.WriteField(key, val)

	}
	err = writer.Close()
	if err != nil {
		fmt.Printf("文件关闭错误: %s\n", err.Error())
		return nil
	}

	req, err := http.NewRequest("POST", url, body)
	req.Header.Set("Content-Type", writer.FormDataContentType())
	for key,value :=range header{
		req.Header.Set(key, value)
	}
	//过滤https证书
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		//关闭连接池,不然会打满语句柄
		DisableKeepAlives: true,
	}

	//设置请求超时时间为20秒
	client := &http.Client{
		Transport: tr,
		Timeout: 20 * time.Second,
	}
	res, err := client.Do(req)
	if res !=nil{
		defer res.Body.Close()
		body, _ := ioutil.ReadAll(res.Body)
		return body
	}
	if err !=nil {
		fmt.Printf("请求错误: %s\n", err.Error())
		return nil
	}
	return nil
}

Request

go 复制代码
/***
url 请求地址
header 头部
requestData 请求数据
method 请求方法
*/
func Request(url string,header map[string]string, requestData []byte, method string) []byte{
	//rwLock.Lock()

	//payload := strings.NewReader(requestData)
	req, _ := http.NewRequest(method, url, bytes.NewBuffer(requestData))
	//req.Header.Set("content-type", "application/json")
	req.Header.Set("cache-control", "no-cache")
	for key,value :=range header{
		req.Header.Set(key, value)
	}
	//过滤https证书
	tr := &http.Transport{
		TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		//关闭连接池,不然会打满语句柄
		DisableKeepAlives: true,
	}

	//设置请求超时时间为20秒
	client := &http.Client{
		Transport: tr,
		Timeout: 20 * time.Second,
	}
	res, err := client.Do(req)
	if res !=nil{
		defer res.Body.Close()
		body, _ := ioutil.ReadAll(res.Body)
		return body
	}
	if err !=nil {
		fmt.Printf("请求错误: %s\n", err.Error())
		return nil
	}
	return nil

}

测试

新建 main.go 文件写入以下内容:

go 复制代码
func main()  {
	sendData :=make(map[string]string)
	sendData["name"]="测试"
	sendData["sex"]="男"
	jsonStr,_:=json.Marshal(sendData)
    
    //此处需要换成你自己的接口地址
	httpUrl:="https://xxxxx/api/test"
	headerData :=make(map[string]string)
	headerData["X-Ca-Key"]="22527885"
	headerData["Content-Type"]="application/json;charset=UTF-8"
	headerData["Accept"]="application/json"
	body:=client.POST(httpUrl,headerData,jsonStr)
	fmt.Printf("请求成功返回:%s\n",body)

}

执行命令:

go run main.go

总结

本文对 net/http 包的简单封装,使用者可以直接拿来用,减少了开发成本。

相关推荐
小杨互联网1 小时前
Go 现代 CLI 工具离线镜像合集
开发语言·后端·golang·开源·go·命令行
microrain4 小时前
跟着一条属性报文走一遍 SagooIoT 的接入链路
物联网·架构·golang·sagooiot
CodeGL4 小时前
微服务框架——go-zero
微服务·架构·golang
嵌入式学习菌5 小时前
HTTP/HTTPS、MQTT/MQTTS 区别
网络协议·http·https
情 九15 小时前
MCP 实战 06:把 HTTP 接口接成工具,让 AI 帮你查数据
人工智能·网络协议·http·mcp
步行cgn1 天前
HTTP 请求报文结构详解:请求行、请求头、请求体各自的作用
网络·网络协议·http
紧跟先前的步伐1 天前
Go AI Agent 实战 22|完善 Agent 执行循环:从工具调用到最终回答
人工智能·ai·golang
后台模板学习1 天前
Go Web开发中任务调度框架的源码解析与高可用实现方案
开发语言·后端·golang
FungLeo1 天前
成为全栈·Go 后端篇·分类树与标签关系:目录变更为何需要协调
golang·go·gorm·数据库事务·分类树·成为全栈
fly-iot1 天前
【FDE知识库】(1):AI 编程时代开发语言选型分析,云使用go,企业用java,算法python,底层c
开发语言·人工智能·golang