一、概述

http 包提供 HTTP 客户端和服务器实现。
官方文档 https://pkg.go.dev/net/http 我们可以多看几遍。
主要的提供的方法有 Get、Head、Post 和 PostForm 。
我们实现的话get请求的话,主要有2种方式

http.Get()
DefaultClient.Get()

然后我们会介绍封装参数,header,transport

二、2种实现方式

2.1 最简单的 http.Get()方法

我们使用http的Get()函数

func Get(url string ) (resp * Response , err error )

Get方法 向指定的 URL 发出 GET。
Get 是 DefaultClient.Get 的包装器。用于没有自定义header的快速请求。

func Test1(t *testing.T) {
    url := fmt.Sprintf("http://localhost:8080/v1/user?id=%d", 1010)
    resp, err := http.Get(url)
    if err != nil {

    }
    // 客户端发起的请求必须在结束的时候关闭 response body
    defer resp.Body.Close()
    body, err := io.ReadAll(resp.Body)
    t.Log(resp, err)
    t.Log(string(body))
}

这个代码,我们可以等价替换为DefaultClient.Get如下

func Test1t(t *testing.T) {
    url := fmt.Sprintf("http://localhost:8080/v1/user?id=%d", 1010)
    resp, err := http.DefaultClient.Get(url)
    if err != nil {

    }
    // 客户端发起的请求必须在结束的时候关闭 response body
    defer resp.Body.Close()
    body, err := io.ReadAll(resp.Body)
    t.Log(resp, err)
    t.Log(string(body))
}

2.2 使用http.NewRequest() 封装header以及param参数

我们先使用 http.NewRequest() 生产一个 Request
然后再使用 http.DefaultClient.Do(Request)来 请求这个Request。

func Test5(t *testing.T) {
    req, err := http.NewRequest("GET", "http://localhost:8080/v1/discovery", nil)
    if err != nil {

    }
    // 增加header
    req.Header.Add("Content-Type", "application/json")

    // 增加请求参数
    params := req.URL.Query()
    params.Add("id", "1010")
    req.URL.RawQuery = params.Encode()

    resp, err := http.DefaultClient.Do(req)
    // 客户端发起的请求必须在结束的时候关闭 response body
    defer resp.Body.Close()
    body, err := io.ReadAll(resp.Body)
    t.Log(resp, err)
    t.Log(string(body))
}

我们这里封装了一个 header请求数据类型Content-Type,用json的格式来请求和处理返回数据。
并且我们处理了 url请求参数 params

三、自定义client

在前面的请求,其实我们用的都是默认的DefaultClient,如果我们想自己定义client,来做一些http的处理呢。
在这里我们自定义http.Client,来控制一下 http请求与返回的标准。

func Test3(t *testing.T) {
    // 要控制代理、TLS 配置、保持活动、压缩和其他设置,请创建一个Transport:
    client := &http.Client{
        Transport: &http.Transport{
            Proxy: nil,
            DialContext: (&net.Dialer{
                Timeout:   30 * time.Second, // 连接超时时间
                Deadline:  time.Time{},
                KeepAlive: 30 * time.Second, // 连接保持超时时间
            }).DialContext,
            DialTLSContext:         nil,
            TLSClientConfig:        nil,
            TLSHandshakeTimeout:    10 * time.Second, // TLS安全连接握手超时时间,
            DisableKeepAlives:      false,
            DisableCompression:     false,
            MaxIdleConns:           100,              // client对与所有host最大空闲连接数总和
            MaxIdleConnsPerHost:    2,                // 每个host 最大空闲链接数
            IdleConnTimeout:        90 * time.Second, // 空闲连接在连接池中的超时时间
            ResponseHeaderTimeout:  0,
            ExpectContinueTimeout:  1 * time.Second, // 发送完请求到接收到响应头的超时时间,
            MaxResponseHeaderBytes: 0,
            WriteBufferSize:        0,
            ReadBufferSize:         0,
        },
        Timeout: 1000 * time.Millisecond, // 总的超时时间
    }

    url := fmt.Sprintf("http://localhost:8080/v1/discovery?id=%d", 1010)
    req, err := http.NewRequest("GET", url, nil)
    if err != nil {

    }
    resp, err := client.Do(req)
    // the client must close the response body when finished with it:
    defer resp.Body.Close()
    body, err := io.ReadAll(resp.Body)
    t.Log(resp, err)
    t.Log(string(body))
}

可以发现在 最后我们用 client.Do()来代替了默认的DefaultClient.Do


海生
104 声望33 粉丝

与黑夜里,追求那一抹萤火。