func (cc *ClientConn) pickFirstUpdateAddresses(addrs []Address) bool {
	if len(cc.conns) == 0 {
		return false
	}
	var currentAc *addrConn
	for _, currentAc = range cc.conns {
		break
	}
	var addrInNewSlice bool
	for _, addr := range addrs {
		if strings.Compare(addr.Addr, currentAc.curAddr.Addr) == 0 {
			addrInNewSlice = true
			break
		}
	}
	if addrInNewSlice {
		cc.conns = make(map[Address]*addrConn)
		for _, addr := range addrs {
			cc.conns[addr] = currentAc
		}
		currentAc.addrs = addrs
		return true
	}
	return false
}
pickFirstUpdateAddresses checks whether current address in the updating list, Update the list if true.
It is only used when the balancer is pick first.
package grpc
import (
	"errors"
	"math"
	"net"
	"strings"
	"sync"
	"time"
	"golang.org/x/net/context"
	"golang.org/x/net/trace"
	"google.golang.org/grpc/connectivity"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/grpclog"
	"google.golang.org/grpc/keepalive"
	"google.golang.org/grpc/stats"
	"google.golang.org/grpc/transport"
)
var (
	ErrClientConnClosing = errors.New("grpc: the client connection is closing")
	ErrClientConnTimeout = errors.New("grpc: timed out when dialing")
	errNoTransportSecurity = errors.New("grpc: no transport security set (use grpc.WithInsecure() explicitly or set credentials)")
	errTransportCredentialsMissing = errors.New("grpc: the credentials require transport level security (use grpc.WithTransportCredentials() to set)")
	errCredentialsConflict = errors.New("grpc: transport credentials are set for an insecure connection (grpc.WithTransportCredentials() and grpc.WithInsecure() are both called)")
	errNetworkIO = errors.New("grpc: failed with network I/O error")
	errConnDrain = errors.New("grpc: the connection is drained")
	errConnClosing = errors.New("grpc: the connection is closing")
	errConnUnavailable = errors.New("grpc: the connection is unavailable")
	errBalancerClosed = errors.New("grpc: balancer is closed")
	minConnectTimeout = 20 * time.Second
)
type dialOptions struct {
	unaryInt    UnaryClientInterceptor
	streamInt   StreamClientInterceptor
	codec       Codec
	cp          Compressor
	dc          Decompressor
	bs          backoffStrategy
	balancer    Balancer
	block       bool
	insecure    bool
	timeout     time.Duration
	scChan      <-chan ServiceConfig
	copts       transport.ConnectOptions
	callOptions []CallOption
}
const (
	defaultClientMaxReceiveMessageSize = 1024 * 1024 * 4
	defaultClientMaxSendMessageSize    = math.MaxInt32
)
type DialOption func(*dialOptions)
func WithInitialWindowSize(s int32) DialOption {
	return func(o *dialOptions) {
		o.copts.InitialWindowSize = s
	}
}
func WithInitialConnWindowSize(s int32) DialOption {
	return func(o *dialOptions) {
		o.copts.InitialConnWindowSize = s
	}
}
func WithMaxMsgSize(s int) DialOption {
	return WithDefaultCallOptions(MaxCallRecvMsgSize(s))
}
func WithDefaultCallOptions(cos ...CallOption) DialOption {
	return func(o *dialOptions) {
		o.callOptions = append(o.callOptions, cos...)
	}
}
func WithCodec(c Codec) DialOption {
	return func(o *dialOptions) {
		o.codec = c
	}
}
func WithCompressor(cp Compressor) DialOption {
	return func(o *dialOptions) {
		o.cp = cp
	}
}
func WithDecompressor(dc Decompressor) DialOption {
	return func(o *dialOptions) {
		o.dc = dc
	}
}
func WithBalancer(b Balancer) DialOption {
	return func(o *dialOptions) {
		o.balancer = b
	}
}
func WithServiceConfig(c <-chan ServiceConfig) DialOption {
	return func(o *dialOptions) {
		o.scChan = c
	}
}
func WithBackoffMaxDelay(md time.Duration) DialOption {
	return WithBackoffConfig(BackoffConfig{MaxDelay: md})
}
func WithBackoffConfig(b BackoffConfig) DialOption {
	setDefaults(&b)
	return withBackoff(b)
}
func withBackoff(bs backoffStrategy) DialOption {
	return func(o *dialOptions) {
		o.bs = bs
	}
}
func WithBlock() DialOption {
	return func(o *dialOptions) {
		o.block = true
	}
}
func WithInsecure() DialOption {
	return func(o *dialOptions) {
		o.insecure = true
	}
}
func WithTransportCredentials(creds credentials.TransportCredentials) DialOption {
	return func(o *dialOptions) {
		o.copts.TransportCredentials = creds
	}
}
func WithPerRPCCredentials(creds credentials.PerRPCCredentials) DialOption {
	return func(o *dialOptions) {
		o.copts.PerRPCCredentials = append(o.copts.PerRPCCredentials, creds)
	}
}
func WithTimeout(d time.Duration) DialOption {
	return func(o *dialOptions) {
		o.timeout = d
	}
}
func WithDialer(f func(string, time.Duration) (net.Conn, error)) DialOption {
	return func(o *dialOptions) {
		o.copts.Dialer = func(ctx context.Context, addr string) (net.Conn, error) {
			if deadline, ok := ctx.Deadline(); ok {
				return f(addr, deadline.Sub(time.Now()))
			}
			return f(addr, 0)
		}
	}
}
func WithStatsHandler(h stats.Handler) DialOption {
	return func(o *dialOptions) {
		o.copts.StatsHandler = h
	}
}
func FailOnNonTempDialError(f bool) DialOption {
	return func(o *dialOptions) {
		o.copts.FailOnNonTempDialError = f
	}
}
func WithUserAgent(s string) DialOption {
	return func(o *dialOptions) {
		o.copts.UserAgent = s
	}
}
func WithKeepaliveParams(kp keepalive.ClientParameters) DialOption {
	return func(o *dialOptions) {
		o.copts.KeepaliveParams = kp
	}
}
func WithUnaryInterceptor(f UnaryClientInterceptor) DialOption {
	return func(o *dialOptions) {
		o.unaryInt = f
	}
}
func WithStreamInterceptor(f StreamClientInterceptor) DialOption {
	return func(o *dialOptions) {
		o.streamInt = f
	}
}
func WithAuthority(a string) DialOption {
	return func(o *dialOptions) {
		o.copts.Authority = a
	}
}
func Dial(target string, opts ...DialOption) (*ClientConn, error) {
	return DialContext(context.Background(), target, opts...)
}
func DialContext(ctx context.Context, target string, opts ...DialOption) (conn *ClientConn, err error) {
	cc := &ClientConn{
		target: target,
		csMgr:  &connectivityStateManager{},
		conns:  make(map[Address]*addrConn),
	}
	cc.csEvltr = &connectivityStateEvaluator{csMgr: cc.csMgr}
	cc.ctx, cc.cancel = context.WithCancel(context.Background())
	for _, opt := range opts {
		opt(&cc.dopts)
	}
	cc.mkp = cc.dopts.copts.KeepaliveParams
	if cc.dopts.copts.Dialer == nil {
		cc.dopts.copts.Dialer = newProxyDialer(
			func(ctx context.Context, addr string) (net.Conn, error) {
				return dialContext(ctx, "tcp", addr)
			},
		)
	}
	if cc.dopts.copts.UserAgent != "" {
		cc.dopts.copts.UserAgent += " " + grpcUA
	} else {
		cc.dopts.copts.UserAgent = grpcUA
	}
	if cc.dopts.timeout > 0 {
		var cancel context.CancelFunc
		ctx, cancel = context.WithTimeout(ctx, cc.dopts.timeout)
		defer cancel()
	}
	defer func() {
		select {
		case <-ctx.Done():
			conn, err = nil, ctx.Err()
		default:
		}
		if err != nil {
			cc.Close()
		}
	}()
	scSet := false
	if cc.dopts.scChan != nil {
		select {
		case sc, ok := <-cc.dopts.scChan:
			if ok {
				cc.sc = sc
				scSet = true
			}
		default:
		}
	}
	if cc.dopts.codec == nil {
		cc.dopts.codec = protoCodec{}
	}
	if cc.dopts.bs == nil {
		cc.dopts.bs = DefaultBackoffConfig
	}
	creds := cc.dopts.copts.TransportCredentials
	if creds != nil && creds.Info().ServerName != "" {
		cc.authority = creds.Info().ServerName
	} else if cc.dopts.insecure && cc.dopts.copts.Authority != "" {
		cc.authority = cc.dopts.copts.Authority
	} else {
		cc.authority = target
	}
	waitC := make(chan error, 1)
	go func() {
		defer close(waitC)
		if cc.dopts.balancer == nil && cc.sc.LB != nil {
			cc.dopts.balancer = cc.sc.LB
		}
		if cc.dopts.balancer != nil {
			var credsClone credentials.TransportCredentials
			if creds != nil {
				credsClone = creds.Clone()
			}
			config := BalancerConfig{
				DialCreds: credsClone,
				Dialer:    cc.dopts.copts.Dialer,
			}
			if err := cc.dopts.balancer.Start(target, config); err != nil {
				waitC <- err
				return
			}
			ch := cc.dopts.balancer.Notify()
			if ch != nil {
				if cc.dopts.block {
					doneChan := make(chan struct{})
					go cc.lbWatcher(doneChan)
					<-doneChan
				} else {
					go cc.lbWatcher(nil)
				}
				return
			}
		}
		if err := cc.resetAddrConn([]Address{{Addr: target}}, cc.dopts.block, nil); err != nil {
			waitC <- err
			return
		}
	}()
	select {
	case <-ctx.Done():
		return nil, ctx.Err()
	case err := <-waitC:
		if err != nil {
			return nil, err
		}
	}
	if cc.dopts.scChan != nil && !scSet {
		select {
		case sc, ok := <-cc.dopts.scChan:
			if ok {
				cc.sc = sc
			}
		case <-ctx.Done():
			return nil, ctx.Err()
		}
	}
	if cc.dopts.scChan != nil {
		go cc.scWatcher()
	}
	return cc, nil
}
type connectivityStateEvaluator struct {
	csMgr               *connectivityStateManager
	mu                  sync.Mutex
	numReady            uint64  
	numConnecting       uint64  
	numTransientFailure uint64  
}
func (cse *connectivityStateEvaluator) recordTransition(oldState, newState connectivity.State) {
	cse.mu.Lock()
	defer cse.mu.Unlock()
	for idx, state := range []connectivity.State{oldState, newState} {
		updateVal := 2*uint64(idx) - 1  
		switch state {
		case connectivity.Ready:
			cse.numReady += updateVal
		case connectivity.Connecting:
			cse.numConnecting += updateVal
		case connectivity.TransientFailure:
			cse.numTransientFailure += updateVal
		}
	}
	if cse.numReady > 0 {
		cse.csMgr.updateState(connectivity.Ready)
		return
	}
	if cse.numConnecting > 0 {
		cse.csMgr.updateState(connectivity.Connecting)
		return
	}
	cse.csMgr.updateState(connectivity.TransientFailure)
}
type connectivityStateManager struct {
	mu         sync.Mutex
	state      connectivity.State
	notifyChan chan struct{}
}
func (csm *connectivityStateManager) updateState(state connectivity.State) {
	csm.mu.Lock()
	defer csm.mu.Unlock()
	if csm.state == connectivity.Shutdown {
		return
	}
	if csm.state == state {
		return
	}
	csm.state = state
	if csm.notifyChan != nil {
		close(csm.notifyChan)
		csm.notifyChan = nil
	}
}
func (csm *connectivityStateManager) getState() connectivity.State {
	csm.mu.Lock()
	defer csm.mu.Unlock()
	return csm.state
}
func (csm *connectivityStateManager) getNotifyChan() <-chan struct{} {
	csm.mu.Lock()
	defer csm.mu.Unlock()
	if csm.notifyChan == nil {
		csm.notifyChan = make(chan struct{})
	}
	return csm.notifyChan
}
type ClientConn struct {
	ctx    context.Context
	cancel context.CancelFunc
	target    string
	authority string
	dopts     dialOptions
	csMgr     *connectivityStateManager
	csEvltr   *connectivityStateEvaluator  
	mu    sync.RWMutex
	sc    ServiceConfig
	conns map[Address]*addrConn
	mkp keepalive.ClientParameters
}
func (cc *ClientConn) WaitForStateChange(ctx context.Context, sourceState connectivity.State) bool {
	ch := cc.csMgr.getNotifyChan()
	if cc.csMgr.getState() != sourceState {
		return true
	}
	select {
	case <-ctx.Done():
		return false
	case <-ch:
		return true
	}
}
func (cc *ClientConn) GetState() connectivity.State {
	return cc.csMgr.getState()
}
func (cc *ClientConn) lbWatcher(doneChan chan struct{}) {
	defer func() {
		if doneChan != nil {
			close(doneChan)
		}
	}()
	_, isPickFirst := cc.dopts.balancer.(*pickFirst)
	for addrs := range cc.dopts.balancer.Notify() {
		if isPickFirst {
			if len(addrs) == 0 {
				cc.mu.Lock()
				if len(cc.conns) != 0 {
					cc.pickFirstAddrConnTearDown()
				}
				cc.mu.Unlock()
			} else {
				cc.resetAddrConn(addrs, true, nil)
				if doneChan != nil {
					close(doneChan)
					doneChan = nil
				}
			}
		} else {
			var (
				add []Address    
				del []*addrConn  
			)
			cc.mu.Lock()
			for _, a := range addrs {
				if _, ok := cc.conns[a]; !ok {
					add = append(add, a)
				}
			}
			for k, c := range cc.conns {
				var keep bool
				for _, a := range addrs {
					if k == a {
						keep = true
						break
					}
				}
				if !keep {
					del = append(del, c)
					delete(cc.conns, k)
				}
			}
			cc.mu.Unlock()
			for _, a := range add {
				var err error
				if doneChan != nil {
					err = cc.resetAddrConn([]Address{a}, true, nil)
					if err == nil {
						close(doneChan)
						doneChan = nil
					}
				} else {
					err = cc.resetAddrConn([]Address{a}, false, nil)
				}
				if err != nil {
					grpclog.Warningf("Error creating connection to %v. Err: %v", a, err)
				}
			}
			for _, c := range del {
				c.tearDown(errConnDrain)
			}
		}
	}
}
func (cc *ClientConn) scWatcher() {
	for {
		select {
		case sc, ok := <-cc.dopts.scChan:
			if !ok {
				return
			}
			cc.mu.Lock()
			cc.sc = sc
			cc.mu.Unlock()
		case <-cc.ctx.Done():
			return
		}
	}
}