Go 1.7からhttp.TransportのCancelRequestがDeprecatedになってcontextという仕組みを使うのが良いとされるようになった。
キャンセルなし
package main
import (
//"context"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := http.DefaultClient
//ctx, cancelFunc := context.WithCancel(context.Background())
req, err := http.NewRequest("GET", "https://google.com/", nil)
if err != nil {
panic(err)
}
//req = req.WithContext(ctx)
ch := make(chan struct{})
go func() {
resp, err := client.Do(req)
if err != nil { // リクエストが成功すればここは通らない
fmt.Println(err)
ch <- struct{}{}
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
ch <- struct{}{}
}()
//cancelFunc()
<-ch
}
キャンセルあり
package main
import (
"context"
"fmt"
"io/ioutil"
"net/http"
)
func main() {
client := http.DefaultClient
ctx, cancelFunc := context.WithCancel(context.Background())
req, err := http.NewRequest("GET", "https://google.com/", nil)
if err != nil {
panic(err)
}
req = req.WithContext(ctx)
ch := make(chan struct{})
go func() {
resp, err := client.Do(req)
if err != nil { // キャンセルされた場合はエラーが返る
fmt.Println(err) // Get https://google.com/: net/http: request canceled while waiting for connection
ch <- struct{}{}
return
}
defer resp.Body.Close()
body, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
fmt.Println(string(body))
ch <- struct{}{}
}()
cancelFunc()
<-ch
}