golang 官方提供的 http 包裏的 http client 可以通過一下兩種方法設置超時(其他一些精細的超時控制比如設置 transport 裏的 dial connect 的超時時間不在這裏討論)。
1 client.Timeout
// 設置1s超時
cli := http.Client{Timeout: time.Second}
2 req.WithContext
// 設置1s超時
req := http.NewRequest(....)
ctx, _ := context.WithTimeout(time.Second)
req.WithContext(ctx)
先說說1,根據 Timeout 設置一個定時器 timer, 然後起一個goroutine等待 timer結束,如果等到就關閉 req.cancel
。參考這裏。關閉req.cancel
會導致當前鏈接關閉從而結束本次請求。參考這裏和這裏
再來說說2,這裏並沒有像1一樣起一個timer,而是根據req.Context
是否結束來判斷是否超時。參考這裏,如果超時,同1一樣,關閉當前鏈接。
這裏總結一下,
- 1 和 2 效果一樣,都是通過關閉當前鏈接結束本次請求。
- 1 和 2 一樣,超時時間都包括 鏈接建立,請求發送,讀取返回。如果沒有及時讀取
resp.Body
,都會引起超時錯誤。