golang提供的http get、post請求是沒有設置超時的,但實現生產環境一般都需要設置超時時間。
網上搜索,可以查詢到通過設置http.Client中Transport的Dail函數,在自定義的Dail函數里面設置建立連接超時時長和發送接收數據超時:
c := http.Client{
Transport: &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, time.Second*3) //設置建立連接超時
if err != nil {
return nil, err
}
c.SetDeadline(time.Now().Add(5 * time.Second)) //設置發送接收數據超時
return c, nil
},
},
}
因為上面的代碼中調用SetDeadline設置了絕對過期時間,這會導致在該連接上發生的第二次及后來的請求的超時與預期的不一致。第一次請求的發送接收數據超時是5s,但第二次請求的發送接收數據超時是5s減去第一次請求發送接收數據耗時(忽略其他輕微耗時),后面的請求以此類推。所以,這種方法只適用於所有的請求都有各自的http.Client,也就是說每次請求都需要創建各自的http.Client,建立各自的連接。
但golang官方文檔里面有說“Clients should be reused instead of created as needed. Clients are safe for concurrent use by multiple goroutines.”(詳見http包中Client的定義說明)。重復利用http.Client,可以考慮如下方法:
var c *http.Client = &http.Client{
Transport: &http.Transport{
Dial: func(netw, addr string) (net.Conn, error) {
c, err := net.DialTimeout(netw, addr, time.Second*3)
if err != nil {
fmt.Println("dail timeout", err)
return nil, err
}
return c, nil
},
MaxIdleConnsPerHost: 10,
ResponseHeaderTimeout: time.Second * 2,
},
}
這里添加了ResponseHeaderTimeout配置,默認是0,無限等待。該設置不包括發送數據超時和接收返回包正文體超時,只能大致的實現發送接收數據超時設置。