Go语言发送http请求常见用法

1. 简介

在日常工作中经常使用Go语言发送http请求,特此编写此文档来总结常见用法,以供日后参考。

使用net/http包来发送http请求,请参考 net/http文档

本文只是为了总结常见用法,仅介绍GETPOST两种http方法,其余方法参考这两种方法的用法即可。支持的方法有:

const (
    MethodGet     = "GET"
    MethodHead    = "HEAD"
    MethodPost    = "POST"
    MethodPut     = "PUT"
    MethodPatch   = "PATCH" // RFC 5789
    MethodDelete  = "DELETE"
    MethodConnect = "CONNECT"
    MethodOptions = "OPTIONS"
    MethodTrace   = "TRACE"
)

2. 实现最简单的GETPOST请求

当你仅需快速实现http请求,无需任何自定义配置时,可以直接使用http包中函数来实现。

例1,使用http.Get函数实现GET请求:

func main() {
    resp, err := http.Get("http://localhost:8080/ping")
    if err != nil {
        fmt.Println("http get failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http get succeed:", string(respBody))
}

例2、使用http.Post函数实现POST请求:

func main() {
    body := bytes.NewReader([]byte(`{"name": "Jack", "sex": "male", "age": 18}`))
    resp, err := http.Post("http://localhost:8080/user", "application/json", body)
    if err != nil {
        fmt.Println("http post failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http post succeed:", string(respBody))
}

3. 使用默认客户端

当你需要自定义http请求而无需自定义客户端时,可以使用http包提供的默认客户端来实现。

例1,为GET请求实现超时控制:

func main() {
    ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancelFunc()
    req, err := http.NewRequestWithContext(ctx, http.MethodGet, "http://localhost:8080/ping", nil)
    if err != nil {
        fmt.Println("new http get request failed:", err)
        return
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("http get failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http get succeed:", string(respBody))
}

例2,为POST请求实现超时控制:

func main() {
    body := bytes.NewReader([]byte(`{"name": "Jack", "sex": "male", "age": 18}`))
    ctx, cancelFunc := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancelFunc()
    req, err := http.NewRequestWithContext(ctx, http.MethodPost, "http://localhost:8080/user", body)
    if err != nil {
        fmt.Println("new http post request failed:", err)
        return
    }
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("http post failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http post succeed:", string(respBody))
}

4. 使用自定义客户端

当你需要控制重定向策略、代理、TLS配置、持久连接、压缩等配置时,你需要创建一个自定义客户端。

例1,为GET请求指定重定向策略:

func main() {
    client := &http.Client{
        CheckRedirect: redirectPolicyFunc,
    }
    req, err := http.NewRequest(http.MethodGet, "http://localhost:8080/ping", nil)
    if err != nil {
        fmt.Println("new http get request failed:", err)
        return
    }
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("http get failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http get succeed:", string(respBody))
}

func redirectPolicyFunc(req *http.Request, via []*http.Request) error {
    return nil
}

例2,为POST请求指定持久连接配置:

func main() {
    tr := &http.Transport{
        MaxIdleConns:       10,
        IdleConnTimeout:    30 * time.Second,
    }
    client := &http.Client{Transport: tr}
    body := bytes.NewReader([]byte(`{"name": "Jack", "sex": "male", "age": 18}`))
    req, err := http.NewRequest(http.MethodPost, "http://localhost:8080/user", body)
    if err != nil {
        fmt.Println("new http post request failed:", err)
        return
    }
    resp, err := client.Do(req)
    if err != nil {
        fmt.Println("http post failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http post succeed:", string(respBody))
}

5. 在url中添加查询参数

当你需要在url中添加查询参数时,可以使用url.Values来添加。

例1,为GET请求在url中添加查询参数:

func main() {
    req, err := http.NewRequest(http.MethodGet, "http://localhost:8080/user", nil)
    if err != nil {
        fmt.Println("new http get request failed:", err)
        return
    }
    params := url.Values{}
    params.Add("name", "Jack")
    req.URL.RawQuery = params.Encode()
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("http get failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http get succeed:", string(respBody))
}

6. 添加请求头

当你需要自定义http请求头时,可以通过RequestHeader成员的SetAdd方法来添加。

例1,为POST请求添加请求头:

func main() {
    body := bytes.NewReader([]byte(`{"name": "Jack", "sex": "male", "age": 18}`))
    req, err := http.NewRequest(http.MethodPost, "http://localhost:8080/user", body)
    if err != nil {
        fmt.Println("new http post request failed:", err)
        return
    }
    req.Header.Set("Content-Type", "application/json")
    req.Header.Add("Accept-Language", "zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7")
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("http post failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    fmt.Println("http post succeed:", string(respBody))
}

7. 上传文件

当你需要上传文件时,可以通过multipart.Writer来实现。

例1,使用multipart.Writer实现上传文件功能:

func main() {
    filePath := "go.mod"
    multipartWriter, reqBody, err := newUploadFile(filePath)
    if err != nil {
        fmt.Println(err)
        return
    }

    req, err := http.NewRequest(http.MethodPost, "http://localhost:8080/file", reqBody)
    if err != nil {
        fmt.Println("create request failed:", err)
        return
    }
    req.Header.Set("Content-Type", multipartWriter.FormDataContentType())
    resp, err := http.DefaultClient.Do(req)
    if err != nil {
        fmt.Println("send request failed:", err)
        return
    }
    defer resp.Body.Close()

    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response failed:", err)
        return
    }
    fmt.Println("upload file succeed:", string(respBody))
}

func newUploadFile(filePath string) (*multipart.Writer, *bytes.Buffer, error) {
    var reqBody bytes.Buffer
    multipartWriter := multipart.NewWriter(&reqBody)
    part, err := multipartWriter.CreateFormFile("upload", filepath.Base(filePath))
    if err != nil {
        return nil, nil, fmt.Errorf("create form file failed: %v", err)
    }

    file, err := os.Open(filePath)
    if err != nil {
        return nil, nil, fmt.Errorf("open file failed: %v", err)
    }
    defer file.Close()

    _, err = io.Copy(part, file)
    if err != nil {
        return nil, nil, fmt.Errorf("copy file content failed: %v", err)
    }

    err = multipartWriter.Close()
    if err != nil {
        return nil, nil, fmt.Errorf("close multipart writer failed: %v", err)
    }
    return multipartWriter, &reqBody, nil
}

8. 下载文件

通过http接口下载文件的实现特别简单,将响应体数据写入本地文件即可。

例1,下载文件到download目录下,从响应头中的Content-Disposition字段提取文件名:

func main() {
    resp, err := http.Get("http://localhost:8080/file")
    if err != nil {
        fmt.Println("http get failed:", err)
        return
    }
    defer resp.Body.Close()
    respBody, err := io.ReadAll(resp.Body)
    if err != nil {
        fmt.Println("read response body failed:", err)
        return
    }
    filename := filenameFromRespHeader(resp.Header)
    err = os.WriteFile(path.Join("download", filename), respBody, os.ModePerm)
    if err != nil {
        return
    }
    fmt.Println("http get succeed:", string(respBody))
}

func filenameFromRespHeader(header http.Header) string {
    r := regexp.MustCompile(`^.*filename="(.*)"`)
    s := header.Get("Content-Disposition")
    ss := r.FindStringSubmatch(s)
    if len(ss) >= 2 {
        return ss[1]
    }
    return "unknown"
}
  • 7
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: Go 语言可以很容易地使用 net/http 包来发送 HTTP 请求,可以使用以下代码实现 post 请求:resp, err := http.Post("http://example.com/upload", "image/jpeg", &buf) ### 回答2: Go语言发送Post请求的步骤如下: 1. 首先,我们需要导入`net/http`库,该库提供了用于发送HTTP请求的功能。 2. 创建一个`http.Client`对象,该对象用于发送HTTP请求。 ```go client := &http.Client{} ``` 3. 创建一个`http.NewRequest`对象,该对象用于构建HTTP请求。通过指定请求的URL、请求方法和请求体等参数来创建该对象。 ```go req, err := http.NewRequest("POST", "http://example.com/api", bytes.NewBuffer([]byte("Request Body"))) ``` 4. 设置请求头信息,例如设置`Content-Type`和`Authorization`等。 ```go req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer token") ``` 5. 发送HTTP请求,并获取响应。 ```go resp, err := client.Do(req) ``` 6. 确保在函数结束后关闭响应体。 ```go defer resp.Body.Close() ``` 7. 从响应中读取数据。 ```go body, err := ioutil.ReadAll(resp.Body) ``` 完整的示例代码如下: ```go package main import ( "bytes" "fmt" "io/ioutil" "net/http" ) func main() { client := &http.Client{} req, err := http.NewRequest("POST", "http://example.com/api", bytes.NewBuffer([]byte("Request Body"))) if err != nil { fmt.Println("Error creating request:", err) return } req.Header.Set("Content-Type", "application/json") req.Header.Set("Authorization", "Bearer token") resp, err := client.Do(req) if err != nil { fmt.Println("Error sending request:", err) return } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("Error reading response:", err) return } fmt.Println("Response:", string(body)) } ``` 这样,我们就可以使用Go语言发送Post请求了。 ### 回答3: 要使用Go语言发送POST http请求,可以使用Go语言标准库中的net/http包。下面是一个简单的示例代码: ```go package main import ( "bytes" "fmt" "io/ioutil" "net/http" ) func main() { url := "http://example.com/api" // 设置请求的URL data := []byte(`{"name": "John", "age": 30}`) // 设置请求的数据 req, err := http.NewRequest("POST", url, bytes.NewBuffer(data)) if err != nil { fmt.Println("创建请求失败:", err) return } // 设置请求头 req.Header.Set("Content-Type", "application/json") // 创建HTTP客户端并发送请求 client := &http.Client{} resp, err := client.Do(req) if err != nil { fmt.Println("发送请求失败:", err) return } defer resp.Body.Close() // 读取响应内容 respData, err := ioutil.ReadAll(resp.Body) if err != nil { fmt.Println("读取响应失败:", err) return } fmt.Println("响应内容:", string(respData)) } ``` 以上代码首先创建了一个POST请求,并设置了请求的URL和数据。然后,通过设置请求头的方式指定了请求数据的类型为JSON。接下来,创建了一个HTTP客户端并发送请求。最后,读取响应的内容,并打印出来。 这仅是一个简单的例子,实际的场景可能还涉及到error处理、身份验证、cookie等。可以根据具体需求进行适当修改。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值