func (s *Stream) Trailer() metadata.MD {
	s.mu.RLock()
	c := s.trailer.Copy()
	s.mu.RUnlock()
	return c
}
Trailer returns the cached trailer metedata. Note that if it is not called
after the entire stream is done, it could return an empty MD. Client
side only.
package transport  
import (
	"fmt"
	"io"
	"net"
	"sync"
	"golang.org/x/net/context"
	"golang.org/x/net/http2"
	"google.golang.org/grpc/codes"
	"google.golang.org/grpc/credentials"
	"google.golang.org/grpc/keepalive"
	"google.golang.org/grpc/metadata"
	"google.golang.org/grpc/stats"
	"google.golang.org/grpc/status"
	"google.golang.org/grpc/tap"
)
type recvMsg struct {
	data []byte
	err error
}
type recvBuffer struct {
	c       chan recvMsg
	mu      sync.Mutex
	backlog []recvMsg
}
func newRecvBuffer() *recvBuffer {
	b := &recvBuffer{
		c: make(chan recvMsg, 1),
	}
	return b
}
func (b *recvBuffer) put(r recvMsg) {
	b.mu.Lock()
	if len(b.backlog) == 0 {
		select {
		case b.c <- r:
			b.mu.Unlock()
			return
		default:
		}
	}
	b.backlog = append(b.backlog, r)
	b.mu.Unlock()
}
func (b *recvBuffer) load() {
	b.mu.Lock()
	if len(b.backlog) > 0 {
		select {
		case b.c <- b.backlog[0]:
			b.backlog[0] = recvMsg{}
			b.backlog = b.backlog[1:]
		default:
		}
	}
	b.mu.Unlock()
}
func (b *recvBuffer) get() <-chan recvMsg {
	return b.c
}
type recvBufferReader struct {
	ctx    context.Context
	goAway chan struct{}
	recv   *recvBuffer
	last   []byte  
	err    error
}
func (r *recvBufferReader) Read(p []byte) (n int, err error) {
	if r.err != nil {
		return 0, r.err
	}
	n, r.err = r.read(p)
	return n, r.err
}
func (r *recvBufferReader) read(p []byte) (n int, err error) {
	if r.last != nil && len(r.last) > 0 {
		copied := copy(p, r.last)
		r.last = r.last[copied:]
		return copied, nil
	}
	select {
	case <-r.ctx.Done():
		return 0, ContextErr(r.ctx.Err())
	case <-r.goAway:
		return 0, errStreamDrain
	case m := <-r.recv.get():
		r.recv.load()
		if m.err != nil {
			return 0, m.err
		}
		copied := copy(p, m.data)
		r.last = m.data[copied:]
		return copied, nil
	}
}
type item interface {
	item()
}
type controlBuffer struct {
	c       chan item
	mu      sync.Mutex
	backlog []item
}
func newControlBuffer() *controlBuffer {
	b := &controlBuffer{
		c: make(chan item, 1),
	}
	return b
}
func (b *controlBuffer) put(r item) {
	b.mu.Lock()
	if len(b.backlog) == 0 {
		select {
		case b.c <- r:
			b.mu.Unlock()
			return
		default:
		}
	}
	b.backlog = append(b.backlog, r)
	b.mu.Unlock()
}
func (b *controlBuffer) load() {
	b.mu.Lock()
	if len(b.backlog) > 0 {
		select {
		case b.c <- b.backlog[0]:
			b.backlog[0] = nil
			b.backlog = b.backlog[1:]
		default:
		}
	}
	b.mu.Unlock()
}
func (b *controlBuffer) get() <-chan item {
	return b.c
}
type streamState uint8
const (
	streamActive    streamState = iota
	streamWriteDone              
	streamReadDone               
	streamDone                   
)
type Stream struct {
	id           uint32
	st           ServerTransport     
	ctx          context.Context     
	cancel       context.CancelFunc  
	done         chan struct{}       
	goAway       chan struct{}       
	method       string              
	recvCompress string
	sendCompress string
	buf          *recvBuffer
	trReader     io.Reader
	fc           *inFlow
	recvQuota    uint32
	waiters      waiters
	requestRead func(int)
	sendQuotaPool *quotaPool
	headerChan    chan struct{}  
	headerDone    bool           
	header        metadata.MD    
	trailer       metadata.MD    
	mu       sync.RWMutex  
	headerOk bool          
	state    streamState
	status *status.Status  
	rstStream bool           
	rstError  http2.ErrCode  
	bytesReceived bool  
	unprocessed   bool  
	contentSubtype string
}
func (s *Stream) waitOnHeader() error {
	if s.headerChan == nil {
		return nil
	}
	wc := s.waiters
	select {
	case <-wc.ctx.Done():
		return ContextErr(wc.ctx.Err())
	case <-wc.goAway:
		return errStreamDrain
	case <-s.headerChan:
		return nil
	}
}
func (s *Stream) RecvCompress() string {
	if err := s.waitOnHeader(); err != nil {
		return ""
	}
	return s.recvCompress
}
func (s *Stream) SetSendCompress(str string) {
	s.sendCompress = str
}
func (s *Stream) Done() <-chan struct{} {
	return s.done
}
func (s *Stream) GoAway() <-chan struct{} {
	return s.goAway
}
func (s *Stream) Header() (metadata.MD, error) {
	err := s.waitOnHeader()
	select {
	case <-s.headerChan:
		return s.header.Copy(), nil
	default:
	}
	return nil, err
}