问小白 wenxiaobai
资讯
历史
科技
环境与自然
成长
游戏
财经
文学与艺术
美食
健康
家居
文化
情感
汽车
三农
军事
旅行
运动
教育
生活
星座命理

Go语言HTTP客户端封装实战:GET、POST和FormData请求

创作时间:
作者:
@小白创作中心

Go语言HTTP客户端封装实战:GET、POST和FormData请求

引用
CSDN
1.
https://blog.csdn.net/qq_30333063/article/details/139383756

本文将详细介绍如何使用Go语言的标准库net/http来封装HTTP客户端,包括GET、POST和FormData请求的方法。通过封装这些常用请求方式,可以大大减少开发成本,提高开发效率。

简介

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

本文将以net/http包作为底层,封装一个包含GET、POST、FormData请求的工具包。

开始

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

GET方法

在client文件中创建如下方法:

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

/**
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

/**
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

/**
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文件写入以下内容:

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包的简单封装,使用者可以直接拿来用,减少了开发成本。

© 2023 北京元石科技有限公司 ◎ 京公网安备 11010802042949号