Description
Please answer these questions before submitting your issue. Thanks!
- What version of Go are you using (
go version
)?
go version go1.6.2 linux/amd64
- What operating system and processor architecture are you using (
go env
)?
GOARCH="amd64"
GOBIN=""
GOEXE=""
GOHOSTARCH="amd64"
GOHOSTOS="linux"
GOOS="linux"
GOPATH="/home/powerman/gocode"
GORACE=""
GOROOT="/usr/lib/go"
GOTOOLDIR="/usr/lib/go/pkg/tool/linux_amd64"
GO15VENDOREXPERIMENT="1"
CC="x86_64-pc-linux-gnu-gcc"
GOGCCFLAGS="-fPIC -m64 -pthread -fmessage-length=0"
CXX="x86_64-pc-linux-gnu-g++"
CGO_ENABLED="1"
- What did you do?
package main
import (
"fmt"
"io"
"io/ioutil"
"net/http"
"runtime"
"time"
)
func main() {
for {
c := &http.Client{
Transport: &http.Transport{
ExpectContinueTimeout: 1 * time.Second, // A
},
}
resp, err := c.Get("http://google.com")
if resp != nil {
io.Copy(ioutil.Discard, resp.Body) // B
resp.Body.Close() // B
}
fmt.Printf("resp=%t, err=%v\n", resp != nil, err)
time.Sleep(time.Second)
c.Transport.(*http.Transport).CloseIdleConnections() // C
runtime.SetFinalizer(c, func(interface{}) { fmt.Println("--- http.Client GONE") })
runtime.SetFinalizer(c.Transport, func(interface{}) { fmt.Println("--- http.Transport GONE") })
runtime.GC()
}
}
- What did you expect to see?
resp=true, err=<nil>
--- http.Client GONE
resp=true, err=<nil>
--- http.Client GONE
--- http.Transport GONE
resp=true, err=<nil>
--- http.Client GONE
--- http.Transport GONE
resp=true, err=<nil>
--- http.Client GONE
--- http.Transport GONE
resp=true, err=<nil>
^Csignal: interrupt
- What did you see instead?
Provided program works correctly and gives output shown above. But if we'll comment any of lines marked // A
or // B
or // C
then http.Transport won't be garbage-collected anymore and output became:
resp=true, err=<nil>
--- http.Client GONE
resp=true, err=<nil>
--- http.Client GONE
resp=true, err=<nil>
--- http.Client GONE
resp=true, err=<nil>
--- http.Client GONE
resp=true, err=<nil>
^Csignal: interrupt
I know it's recommended to share same http.Client for all application, but I'm developing load-testing application which simulate thousands of independent clients and thus require own simulated client to use own http.Client and own http.Transport objects to behave more like real independent clients.