继续浏览精彩内容
慕课网APP
程序员的梦工厂
打开
继续
感谢您的支持,我会继续努力的
赞赏金额会直接到老师账户
将二维码发送给自己后长按识别
微信支付
支付宝支付

Golang 中 Post & Get 请求

POPMUISE
关注TA
已关注
手记 273
粉丝 80
获赞 423

主要记录一下使用过程中碰到的问题。

主要参考:网络请求 & 超时设置

三方库:form & 自己的 fork

注意事项

  1. 请求一定需要记住关闭 Body,否则容易造成资源无法重用导致堵死,源码如下。并且,Get, Post, or PostForm 都是使用了 client.Do 这个方法,因此都需要手动关闭

    package http
    type Client
    func Do:// If the returned error is nil, the Response will contain a non-nil// Body which the user is expected to close. If the Body is not// closed, the Client's underlying RoundTripper (typically Transport)// may not be able to re-use a persistent TCP connection to the server// for a subsequent "keep-alive" request.当然如果返回错误是会自动关闭的
  2. 如果使用 NewRequest 来进行 POST 的表单提交,记得设置头部:

    req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

  3. DefaultClient 中默认不会设置超时时间,普通使用没问题,但是如果在服务端生产环境比较容易导致问题 吐嘈文 比较难搞的是所有的封装好的函数,包括:http.Post http.Get 之类的,都使用的是 DefaultClient 。因此最好是平时使用的时候也设置一个超时时间

    httpClient := &http.Client{
     Timeout: 10 * time.Second,
    }
    res, err := httpClient.Get("some url")if err != nil {
     logs.Warn("something wrong here: %s", err.Error()) return}
    defer res.Body.Close()


普通使用

首先记录一下最简单的请求方式:

// GethttpClient := &http.Client{
    Timeout: 10 * time.Second,
}
res, err := httpClient.Get("some url")if err != nil {
    logs.Warn("something wrong here: %s", err.Error())    return}
defer res.Body.Close()// PosthttpClient := &http.Client{
    Timeout: 10 * time.Second,
}
res, err := httpClient.Post("some url", "", nil)if err != nil {
    logs.Warn("something wrong here: %s", err.Error())    return}
defer res.Body.Close()

数据提交时的处理

主要是记录 Post 提交的时候,构造一个表单数据,同时增加几个头部字段。

使用到了三方库:my form fork from form 主要是修改了空值处理还有标记处理:PR

Tag 处理:

原库默认使用 form 做标记,需要这样定义模型: 
type PostData struct {
  Data1  string `form:"data1" json:"data1"`
  Data2 string `json:"data2"`
}
默认不会去解析 json 标记,所以 data2 不会包括在请求参数中。Po 主稍微改了一下,默认先检测 form,没有则去检测 json 标记,方便不想写两个重复的 tag 的情况:
type PostData struct {
  Data1 string `form:"data1" json:"data1"`
  Data2 string `json:"data2"`
  Data3 string `json:"-"`
}
Po 主的库对于这种情况解析出来的数据参数有 data1 & data2,原库解析出来的数据有 data1 
见仁见智吧,我还是不想写重复的标记

空值处理:原库默认不包含空值

原库对 `空值` 的处理如下:(空值包括 false & 0)
foo := map[string]interface{}{"b": false, "i": 0}
form.EncodeToString(foo)
得到的结果是这样:"b=&i="默认不包括空值,只有设置了空值操作之后才行:
keepZeros := truedelimiter := '.'escape := '\\'form.EncodeToStringWith(foo, delimiter, escape, keepZeros)
得到的结果是这样:"b=false&i=0"

空值处理:默认直接包含空值,正好和原库相反

Po 主库对 `空值` 的处理如下:(空值包括 false & 0)
foo := map[string]interface{}{"b": false, "i": 0}
form.EncodeToString(foo)
得到的结果是这样:"b=false&i=0"默认包括空值,设置了空值操作之后:
form.EncodeToStringWith(foo, true)
得到的结果是这样:"b=&i="

Post form 的使用样例

httpClient := &http.Client{
    Timeout: 10 * time.Second,
}
data := map[string]interface{}{"b": false, "i": 0}
formData, err := form.EncodeToString(data)if err != nil {    return}
req, err := httpClient.NewRequest("POST", "some url", strings.NewReader(formData))if err != nil {    return}
req.Header.Set("Content-Type", "application/x-www-form-urlencoded;charset=utf-8;")
res, err := client.Do(req)if err != nil {    return}
defer res.Body.Close()



作者:HughFace
链接:https://www.jianshu.com/p/2d429f6efbfc

打开App,阅读手记
0人推荐
发表评论
随时随地看视频慕课网APP