Go設置http請求超時的方法實現
背景
最近接手了一個老項目進行維護,發(fā)現其中有個關于 http 請求的方法設置的 timeout 沒有生效,很奇怪!
一開始查看代碼并沒有發(fā)現什么可疑點,后查看了源碼,打斷點調試才發(fā)現問題所在,這里簡單記錄復盤一下。
說明:本篇的源碼的 go 版本是 1.20.2 。
問題
示例代碼
package main
import (
"context"
"fmt"
"net/http"
"time"
)
func main() {
req, err := http.NewRequest(http.MethodGet, "https://www.baidu.com", nil)
if err != nil {
panic(err)
}
ctx, cancel := context.WithTimeout(context.Background(), time.Millisecond)
defer cancel()
req.WithContext(ctx)
resp, err := http.DefaultClient.Do(req)
if err != nil {
panic(err)
}
//resp.Write(os.Stdout)
fmt.Println("end: ", resp.StatusCode)
}
程序正常跑完并輸出了,但是預期的是 http.DefaultClient.Do(req) 這里會直接報錯,難道請求 1ms 就結束了??Why???
大家可以自己看下這段代碼哪里有問題。
先說解決,其實就是 req.WithContext(ctx) 生成的是一個新的 http.Request 對象,上述的問題代碼中并沒有將其賦值給當前的 http.Request。大意了,沒有閃。
req = req.WithContext(ctx)
WithContext 方法的源碼如下(net/http/request.go 356)
func (r *Request) WithContext(ctx context.Context) *Request {
if ctx == nil {
panic("nil context")
}
r2 := new(Request)
*r2 = *r
r2.ctx = ctx
return r2
}
請求超時設置
翻了下源碼,看了下超時設置的方式,http 設置超時主要有兩種方式:
- http.Client
c := http.Client{
Timeout: time.Minute,
}
c.Do(req)
- http.Request 設置 context 超時
ctx, cancel := context.WithTimeout(context.Background(), time.Minute) defer cancel() req = req.WithContext(ctx)
在 Client 上指定 Timeout 會作用于通過該 Client 發(fā)起的所有請求,而 Request 設置 Context,僅針對這一次請求。使用的時候需要注意自己的場景。
設置 Tcp 連接階段的超時可以這樣:
client := http.Client{
Transport: &http.Transport{
Dial: (&net.Dialer{
Timeout: 2 * time.Second, // tcp 連接時設置的連接超時
Deadline: time.Now().Add(3 * time.Second), // 超時強制關閉
}).Dial,
TLSHandshakeTimeout: 2 * time.Second, //https 握手超時
},
Timeout: 5 * time.Second,
}
可以設置 Transport 中的 Dial。
總結
平常自己使用 http 發(fā)送請求設置超時,都是直接給 http.Client 對象設置 Timeout 屬性,很少使用這種對單個 Request 設置超時的。
其實還是個熟練度問題,平常源碼讀的比較少。有空讀讀源碼不僅可以在使用代碼的時候更得心應手,也能夠學習借鑒源碼的代碼設計實現。對自己平常經常需要使用的庫,還是建議都過一遍源碼,很不錯的一個打發(fā)空閑時間的方式。
以上就是Go設置http請求超時的方法實現的詳細內容,更多關于Go設置http請求超時的資料請關注腳本之家其它相關文章!
相關文章
關于golang中map使用的幾點注意事項總結(強烈推薦!)
map是一種無序的基于key-value的數據結構,Go語言中的map是引用類型,必須初始化才能使用,下面這篇文章主要給大家介紹了關于golang中map使用的幾點注意事項,需要的朋友可以參考下2023-01-01

