主要记录一下使用过程中碰到的问题。
注意事项
-
请求一定需要记住关闭 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. 当然如果返回错误是会自动关闭的
-
如果使用 NewRequest 来进行 POST 的表单提交,记得设置头部:
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
-
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()
普通使用
首先记录一下最简单的请求方式:
// Get
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()
// Post
httpClient := &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 := true
delimiter := '.'
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()
网友评论