我正在使用http.Client长轮询的客户端实现:
http.Client
resp, err := client.Post(url, "application/json", bytes.NewBuffer(jsonPostBytes)) if err != nil { panic(err) } defer resp.Body.Close() var results []*ResponseMessage err = json.NewDecoder(resp.Body).Decode(&results) // code blocks here on long-poll
是否有一种标准方法可以从客户端抢占/取消请求?
我想调用resp.Body.Close()会做到这一点,但是我不得不从另一个goroutine调用它,因为通常在读取长轮询的响应时,客户端通常已经被阻塞。
resp.Body.Close()
我知道有一种方法可以通过设置超时http.Transport,但是我的应用逻辑需要根据用户操作(而不只是超时)进行取消。
http.Transport
不,client.Post是90%不需要取消请求的用例的便捷包装。
重新实现您的客户端以访问具有CancelRequest()函数的基础传输对象可能就足够了。
只是一个简单的例子:
package main import ( "log" "net/http" "time" ) func main() { req, _ := http.NewRequest("GET", "http://google.com", nil) tr := &http.Transport{} // TODO: copy defaults from http.DefaultTransport client := &http.Client{Transport: tr} c := make(chan error, 1) go func() { resp, err := client.Do(req) // handle response ... _ = resp c <- err }() // Simulating user cancel request channel user := make(chan struct{}, 0) go func() { time.Sleep(100 * time.Millisecond) user <- struct{}{} }() for { select { case <-user: log.Println("Cancelling request") tr.CancelRequest(req) case err := <-c: log.Println("Client finished:", err) return } } }