Chart
Transport

Client

Code
Transport
type Transport struct { idleMu sync.Mutex closeIdle bool // user has requested to close all idle conns idleConn map[connectMethodKey][]*persistConn // most recently used at end idleConnWait map[connectMethodKey]wantConnQueue // waiting getConns idleLRU connLRU reqMu sync.Mutex reqCanceler map[*Request]func(error) altMu sync.Mutex // guards changing altProto only altProto atomic.Value // of nil or map[string]RoundTripper, key is URI scheme connsPerHostMu sync.Mutex connsPerHost map[connectMethodKey]int connsPerHostWait map[connectMethodKey]wantConnQueue // waiting getConns...}
wantConnQueue
// A wantConnQueue is a queue of wantConns.type wantConnQueue struct { // This is a queue, not a deque. // It is split into two stages - head[headPos:] and tail. // popFront is trivial (headPos++) on the first stage, and // pushBack is trivial (append) on the second stage. // If the first stage is empty, popFront can swap the // first and second stages to remedy the situation. // // This two-stage split is analogous to the use of two lists // in Okasaki's purely functional queue but without the // overhead of reversing the list when swapping stages. head []*wantConn headPos int tail []*wantConn}
wantConn
// A wantConn records state about a wanted connection// (that is, an active call to getConn).// The conn may be gotten by dialing or by finding an idle connection,// or a cancellation may make the conn no longer wanted.// These three options are racing against each other and use// wantConn to coordinate and agree about the winning outcome.type wantConn struct { cm connectMethod key connectMethodKey // cm.key() ctx context.Context // context for dial ready chan struct{} // closed when pc, err pair is delivered // hooks for testing to know when dials are done // beforeDial is called in the getConn goroutine when the dial is queued. // afterDial is called when the dial is completed or cancelled. beforeDial func() afterDial func() mu sync.Mutex // protects pc, err, close(ready) pc *persistConn err error}
persistConn
persistConn struct { // alt optionally specifies the TLS NextProto RoundTripper. // This is used for HTTP/2 today and future protocols later. // If it's non-nil, the rest of the fields are unused. alt RoundTripper t *Transport cacheKey connectMethodKey conn net.Conn tlsState *tls.ConnectionState br *bufio.Reader // from conn bw *bufio.Writer // to conn nwrite int64 // bytes written reqch chan requestAndChan // written by roundTrip; read by readLoop writech chan writeRequest // written by roundTrip; read by writeLoop closech chan struct{} // closed when conn closed isProxy bool sawEOF bool // whether we've seen EOF from conn; owned by readLoop readLimit int64 // bytes allowed to be read; owned by readLoop // writeErrCh passes the request write error (usually nil) // from the writeLoop goroutine to the readLoop which passes // it off to the res.Body reader, which then uses it to decide // whether or not a connection can be reused. Issue 7569. writeErrCh chan error writeLoopDone chan struct{} // closed when write loop ends // Both guarded by Transport.idleMu: idleAt time.Time // time it last become idle idleTimer *time.Timer // holding an AfterFunc to close it mu sync.Mutex // guards following fields numExpectedResponses int closed error // set non-nil when conn is closed, before closech is closed canceledErr error // set non-nil if conn is canceled broken bool // an error has happened on this connection; marked broken so it's not reused. reused bool // whether conn has had successful request/response and is being reused. // mutateHeaderFunc is an optional func to modify extra // headers on each outbound request before it's written. (the // original Request given to RoundTrip is not modified) mutateHeaderFunc func(Header)}
Client
type RoundTripper interface { RoundTrip(*Request) (*Response, error)}type Client struct { Transport RoundTripper CheckRedirect func(req *Request, via []*Request) error Jar CookieJar Timeout time.Duration}var DefaultTransport RoundTripper = &Transport{ Proxy: ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, DualStack: true, }).DialContext, ForceAttemptHTTP2: true, MaxIdleConns: 100, IdleConnTimeout: 90 * time.Second, TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second,}