以下代码是使用 net/http 包实现的 Http 连接池,完整代码在最后

创建连接池

初始化连接池属性


常用属性说明:

属性说明
Dial(已弃用)提供用于创建未加密的TCP连接的方法
DialContext提供用于创建未加密的TCP连接的方法,若DialContext和Dial都未设置默认使用net包下的dial函数
DialTLS(已弃用)提供用于创建非代理HTTPS的TLS请求的方法
DialTLSContext提供用于创建非代理HTTPS的TLS请求的方法
设置之后,HTTPS请求将不使用 DialContext 和 Dial 的相关配置
若 DialTLSContext 和 DialTLS 都未设置,默认使用 DialContext 和 TLSClientConfig 的配置
TLSClientConfig指定要与一起使用的TLS配置
TLSHandshakeTimeoutTLS连接握手超时时长
DisableKeepAlives如果设置为 true 表示一个连接只能让一个请求使用,不能重用
DisableCompression如果设置为 true 则阻止传输使用“Accept Encoding:gzip”请求压缩
MaxIdleConns所有host允许的最大空闲连接数
MaxIdleConnsPerHost单个host允许的最大空闲连接数,如果设置为 0 则使用默认值 2
MaxConnsPerHost单个host允许的最大连接数,设置 0 则表示无限制
IdleConnTimeout连接存活时长,设置 0 表示无限制
ResponseHeaderTimeout响应头接收超时时长,不包含响应体
MaxResponseHeaderBytes响应头内容长度最大限制,设置 0 使用默认限制
WriteBufferSize指定写入传输时使用的写入缓冲区的大小,设置 0 默认 4KB
ReadBufferSize指定从传输中读取时使用的读取缓冲区的大小,设置 0 默认 4KB
ForceAttemptHTTP2true 使用HTTP2(前提是配置了 Dial 或 DialTLS 或 DialContext 方法 或提供了 TLSClientConfig 配置)

创建并初始化连接池

结构体

大部分下情况下,我们请求的接口都需要带有各种请求头信息,例如Cookie。
将请求头信息存放在结构体实例中,后续这个实例发起的请求都将带有同样的请求头信息。

GET方法

如果不需要任何请求头信息,我们可以直接使用 httpClient.Get 去请求接口

如果我们要设置请求头信息,要先使用 http.NewRequest 声明一个请求,塞入 Header 数据并最后由 httpClient 执行

接收到响应后,处理结果是我们要记得及时关闭响应流

POST方法

与Get方法相差无几,我们在POST请求中通常会传递请求体。对于请求体的处理如下:

完整代码

package cus_http

import (
	"bytes"
	"encoding/json"
	"io/ioutil"
	"net"
	"net/http"
	"time"
)

// 初始化连接池配置
var httpTrans = &http.Transport{
	DialContext: (&net.Dialer{
		Timeout:   30 * time.Second,
		KeepAlive: 30 * time.Second,
	}).DialContext,
	ForceAttemptHTTP2:     true,
	MaxIdleConns:          100,                                     //所有Host的连接池最大空闲连接数
	MaxIdleConnsPerHost:   2,                                       //每个Host的连接池最大空闲连接数
	MaxConnsPerHost:       4,                                       //每个Host的连接池最大连接数
	IdleConnTimeout:       time.Duration(90000) * time.Millisecond, //空闲连接保留时间
	TLSHandshakeTimeout:   10 * time.Second,
	ExpectContinueTimeout: 1 * time.Second,
}

// 初始化连接池
var httpClient = &http.Client{
	Timeout:   30 * time.Second,
	Transport: httpTrans,
}

type CusHttp struct {
	Header map[string]string
}

// 发送GET请求
// url:         请求地址
func (cus *CusHttp) Get(url string) string {

	// resp, err := httpClient.Get(url)

	//初始化请求
	reqest, err := http.NewRequest("GET", url, nil)

	//增加Header选项
	if cus.Header != nil && len(cus.Header) > 0 {
		for k, vla := range cus.Header {
			reqest.Header.Add(k, vla)
		}
	}

	if err != nil {
		panic(err)
	}

	resp, err := httpClient.Do(reqest)

	if err != nil {
		panic(err)
	}
	defer resp.Body.Close()

	result, _ := ioutil.ReadAll(resp.Body)
	return string(result)
}

// 发送POST请求 默认使用
// url:         请求地址
// data:        POST请求提交的数据
func (cus *CusHttp) Post(url string, data interface{}) string {
	return cus.post(url, data)
}

// 发送POST 表单
// url:         请求地址
// data:        POST请求提交的数据
func (cus *CusHttp) PostForm(url string, data interface{}) string {
	cus.Header["Content-Type"] = "application/x-www-form-urlencoded"
	return cus.post(url, data)
}

// 发送POST请求
// url:         请求地址
// data:        POST请求提交的数据
func (cus *CusHttp) post(url string, data interface{}) string {

	jsonStr, _ := json.Marshal(data)
	//初始化请求
	reqest, err := http.NewRequest("POST", url, bytes.NewBuffer(jsonStr))
	//增加Header选项
	if cus.Header != nil && len(cus.Header) > 0 {
		for k, vla := range cus.Header {
			reqest.Header.Add(k, vla)
		}
	}

	if err != nil {
		panic(err)
	}

	resp, err := httpClient.Do(reqest)
	if err != nil {
		panic(err)
	}

	defer resp.Body.Close()

	result, _ := ioutil.ReadAll(resp.Body)
	return string(result)
}

测试


结果