func (c *Client) CallWithContext(ctx context.Context, method string, args interface{}, reply interface{}) error {
	call := c.Go(method, args, reply, make(chan *Call, 1))
	select {
	case <-call.Done:
		return call.Error
	case <-ctx.Done():
		return ctx.Err()
	}
	return nil
}
CallWithContext invokes the named function, waits for it to complete, and
returns its error status, or an error from Context timeout.
package rpc2
import (
	"context"
	"errors"
	"io"
	"log"
	"reflect"
	"sync"
)
type Client struct {
	mutex      sync.Mutex  
	sending    sync.Mutex
	request    Request  
	seq        uint64
	pending    map[uint64]*Call
	closing    bool
	shutdown   bool
	server     bool
	codec      Codec
	handlers   map[string]*handler
	disconnect chan struct{}
	State      *State  
	blocking   bool    
}
func NewClient(conn io.ReadWriteCloser) *Client {
	return NewClientWithCodec(NewGobCodec(conn))
}
func NewClientWithCodec(codec Codec) *Client {
	return &Client{
		codec:      codec,
		pending:    make(map[uint64]*Call),
		handlers:   make(map[string]*handler),
		disconnect: make(chan struct{}),
		seq:        1,  
	}
}
func (c *Client) SetBlocking(blocking bool) {
	c.blocking = blocking
}
func (c *Client) Run() {
	c.readLoop()
}
func (c *Client) DisconnectNotify() chan struct{} {
	return c.disconnect
}
func (c *Client) Handle(method string, handlerFunc interface{}) {
	addHandler(c.handlers, method, handlerFunc)
}
func (c *Client) readLoop() {
	var err error
	var req Request
	var resp Response
	for err == nil {
		req = Request{}
		resp = Response{}
		if err = c.codec.ReadHeader(&req, &resp); err != nil {
			break
		}
		if req.Method != "" {
			if err = c.readRequest(&req); err != nil {
				debugln("rpc2: error reading request:", err.Error())
			}
		} else {
			if err = c.readResponse(&resp); err != nil {
				debugln("rpc2: error reading response:", err.Error())
			}
		}
	}
	c.sending.Lock()
	c.mutex.Lock()
	c.shutdown = true
	closing := c.closing
	if err == io.EOF {
		if closing {
			err = ErrShutdown
		} else {
			err = io.ErrUnexpectedEOF
		}
	}
	for _, call := range c.pending {
		call.Error = err
		call.done()
	}
	c.mutex.Unlock()
	c.sending.Unlock()
	if err != io.EOF && !closing && !c.server {
		debugln("rpc2: client protocol error:", err)
	}
	close(c.disconnect)
	if !closing {
		c.codec.Close()
	}
}
func (c *Client) handleRequest(req Request, method *handler, argv reflect.Value) {
	replyv := reflect.New(method.replyType.Elem())
	returnValues := method.fn.Call([]reflect.Value{reflect.ValueOf(c), argv, replyv})
	if req.Seq == 0 {
		return
	}
	errInter := returnValues[0].Interface()
	errmsg := ""
	if errInter != nil {
		errmsg = errInter.(error).Error()
	}
	resp := &Response{
		Seq:   req.Seq,
		Error: errmsg,
	}
	if err := c.codec.WriteResponse(resp, replyv.Interface()); err != nil {
		debugln("rpc2: error writing response:", err.Error())
	}
}
func (c *Client) readRequest(req *Request) error {
	method, ok := c.handlers[req.Method]
	if !ok {
		resp := &Response{
			Seq:   req.Seq,
			Error: "rpc2: can't find method " + req.Method,
		}
		return c.codec.WriteResponse(resp, resp)
	}
	var argv reflect.Value
	argIsValue := false  
	if method.argType.Kind() == reflect.Ptr {
		argv = reflect.New(method.argType.Elem())
	} else {
		argv = reflect.New(method.argType)
		argIsValue = true
	}
	if err := c.codec.ReadRequestBody(argv.Interface()); err != nil {
		return err
	}
	if argIsValue {
		argv = argv.Elem()
	}
	if c.blocking {
		c.handleRequest(*req, method, argv)
	} else {
		go c.handleRequest(*req, method, argv)
	}
	return nil
}
func (c *Client) readResponse(resp *Response) error {
	seq := resp.Seq
	c.mutex.Lock()
	call := c.pending[seq]
	delete(c.pending, seq)
	c.mutex.Unlock()
	var err error
	switch {
	case call == nil:
		err = c.codec.ReadResponseBody(nil)
		if err != nil {
			err = errors.New("reading error body: " + err.Error())
		}
	case resp.Error != "":
		call.Error = ServerError(resp.Error)
		err = c.codec.ReadResponseBody(nil)
		if err != nil {
			err = errors.New("reading error body: " + err.Error())
		}
		call.done()
	default:
		err = c.codec.ReadResponseBody(call.Reply)
		if err != nil {
			call.Error = errors.New("reading body " + err.Error())
		}
		call.done()
	}
	return err
}
func (c *Client) Close() error {
	c.mutex.Lock()
	if c.shutdown || c.closing {
		c.mutex.Unlock()
		return ErrShutdown
	}
	c.closing = true
	c.mutex.Unlock()
	return c.codec.Close()
}
func (c *Client) Go(method string, args interface{}, reply interface{}, done chan *Call) *Call {
	call := new(Call)
	call.Method = method
	call.Args = args
	call.Reply = reply
	if done == nil {
		done = make(chan *Call, 10)  
	} else {
		if cap(done) == 0 {
			log.Panic("rpc2: done channel is unbuffered")
		}
	}
	call.Done = done
	c.send(call)
	return call
}