以下代码是使用 net/http 包实现的 Http 连接池,完整代码在最后
文章目录
- 创建连接池
- 初始化连接池属性
- 创建并初始化连接池
- 结构体
- GET方法
- POST方法
- 完整代码
- 测试
创建连接池
初始化连接池属性
常用属性说明:
属性 | 说明 |
Dial | (已弃用)提供用于创建未加密的TCP连接的方法 |
DialContext | 提供用于创建未加密的TCP连接的方法,若DialContext和Dial都未设置默认使用net包下的dial函数 |
DialTLS | (已弃用)提供用于创建非代理HTTPS的TLS请求的方法 |
DialTLSContext | 提供用于创建非代理HTTPS的TLS请求的方法 设置之后,HTTPS请求将不使用 DialContext 和 Dial 的相关配置 若 DialTLSContext 和 DialTLS 都未设置,默认使用 DialContext 和 TLSClientConfig 的配置 |
TLSClientConfig | 指定要与一起使用的TLS配置 |
TLSHandshakeTimeout | TLS连接握手超时时长 |
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 |
ForceAttemptHTTP2 | true 使用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)
}
测试
结果