Go類型安全的HTTP請求示例詳解
前言
對 Gopher 來說,雖然我們基本都是在寫代碼讓別人來請求,但是有時候,我們也需要去請求第三方提供的 RESTful 接口,這個時候,我們才能感受到前端同學(xué)拼接 HTTP 請求參數(shù)的痛苦。
比如,我們要發(fā)起類似這樣一個請求,看起來很簡單,實際寫起來還是比較繁瑣的。
POST /articles/5/update?device=ios HTTP/1.1 Host: go-zero.dev Authorization: Bearer <jwt-token> {"author":"kevin","body":"this is not important!","title":"my title","type":6}
Go 原生寫法
這個 API 其實是蠻簡單的,我們直接上手就可以寫出來。
func main() { var buf bytes.Buffer encoder := json.NewEncoder(&buf) params := map[string]interface{}{ "title": "my title", "body": "this is not important!", "author": "kevin", "type": 6, } if err := encoder.Encode(params); err != nil { fmt.Fprintln(os.Stderr, err) return } url := fmt.Sprintf("http://localhost:3333/articles/%d/update?device=%s", 5, "ios") req, err := http.NewRequest(http.MethodPost, url, &buf) if err != nil { fmt.Fprintln(os.Stderr, err) return } req.Header.Add("Authorization", "Bearer <jwt-token>") cli := http.Client{} resp, err := cli.Do(req) if err != nil { fmt.Fprintln(os.Stderr, err) return } io.Copy(os.Stdout, resp.Body) }
我們跑了測試一下,發(fā)現(xiàn)沒有得到 200 OK,抓包看一下,請求如下。各位不要往下看,你能想到失敗的原因嗎?
POST /articles/5/update?device=ios HTTP/1.1 Host: go-zero.dev User-Agent: Go-http-client/1.1 Content-Length: 79 Authorization: Bearer <jwt-token> Accept-Encoding: gzip {"author":"kevin","body":"this is not important!","title":"my title","type":6}
具體失敗原因這里就不細講了,我們先來分析這段代碼??梢钥吹狡渲袨榱似唇訁?shù)使用了 map[string]interface{},對于其中每個字段我們是不能校驗類型是否匹配的,只有發(fā)送出去了,收到了服務(wù)端的 200 OK,我們才能確認傳對了。比如其中的 type 參數(shù),這里是使用了 int 類型,我們可能順手寫成 string 類型,但是不請求我們還是很難發(fā)現(xiàn)這個參數(shù)寫錯了的。
那么讓我們看看 go-zero 里 httpc 包是怎么使用并保證類型安全的。
httpc 實現(xiàn)
我們看看用 httpc 包來請求的代碼怎么寫。
const url = "http://go-zero.dev/articles/:id/update" type UpdateArticle struct { ID int `path:"id"` Device string `form:"device,options=ios,android,web,desktop"` Authorization string `header:"Authorization"` Title string `json:"title"` Body string `json:"body"` Author string `json:"author"` Type int `json:"type"` } func main() { data := &UpdateArticle{ ID: 5, Device: "ios", Authorization: "Bearer <jwt-token>", Title: "my title", Body: "this is not important!", Author: "kevin", Type: 6, } resp, err := httpc.Do(context.Background(), http.MethodPost, url, data) if err != nil { fmt.Fprintln(os.Stderr, err) return } io.Copy(os.Stdout, resp.Body) }
寫完測試一下,結(jié)果正如預(yù)期:
POST /articles/5/update?device=ios HTTP/1.1 Host: go-zero.dev User-Agent: Go-http-client/1.1 Content-Length: 79 Content-Type: application/json; charset=utf-8 Authorization: Bearer <jwt-token> Accept-Encoding: gzip {"author":"kevin","body":"this is not important!","title":"my title","type":6}
你發(fā)現(xiàn)了沒有,跟前面的對比,其中多了 Content-Type: application/json; charset=utf-8,而我們之前寫法里忘記設(shè)置 Content-Type 了。
而 httpc 的寫法只要定義好請求的類型,然后通過 httpc.Do 就可以做到類型安全,并且代碼非常精簡。支持了如我們代碼所示的 path、form、header 和 json,可以非常方便且類型安全的發(fā)送 HTTP 請求。
更多能力
除了上面展示的簡單易用和類型安全以外,httpc 包還有以下特點:
- context 的超時控制
- OpenTelemetry 自動集成,服務(wù)端返回的 trace-id, span-id 都會自動被記錄到日志里,便于后續(xù)客戶端、服務(wù)端協(xié)同查問題
- 可以通過 httpc.Service 來獲得熔斷能力,當服務(wù)端有問題,會自動熔斷隔離請求,避免浪費時間等待和加劇服務(wù)端壓力
以上就是Go類型安全的HTTP請求示例詳解的詳細內(nèi)容,更多關(guān)于Go類型安全HTTP請求的資料請關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
詳解golang 定時任務(wù)time.Sleep和time.Tick實現(xiàn)結(jié)果比較
本文主要介紹了golang 定時任務(wù)time.Sleep和time.Tick實現(xiàn)結(jié)果比較,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下2022-02-02Go 庫bytes.Buffer和strings.Builder使用及性能對比
這篇文章主要為大家介紹了Go 庫bytes.Buffer和strings.Builder使用及性能對比,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-12-12Go語言同步等待組sync.WaitGroup結(jié)構(gòu)體對象方法詳解
這篇文章主要為大家介紹了Go語言同步等待組sync.WaitGroup結(jié)構(gòu)體對象方法詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-08-08