func (m *MuxConn) Read(p []byte) (int, error) {
	if n, err := m.buf.Read(p); err != io.EOF {
		return n, err
	}
	return m.Conn.Read(p)
}
From the io.Reader documentation:

When Read encounters an error or end-of-file condition after
successfully reading n > 0 bytes, it returns the number of
bytes read.  It may return the (non-nil) error from the same call
or return the error (and n == 0) from a subsequent call.
An instance of this general case is that a Reader returning
a non-zero number of bytes at the end of the input stream may
return either err == EOF or err == nil.  The next Read should
return 0, EOF.
package cmux
import (
	"bytes"
	"fmt"
	"io"
	"net"
	"sync"
)
type Matcher func(io.Reader) bool
type ErrorHandler func(error) bool
var _ net.Error = ErrNotMatched{}
type ErrNotMatched struct {
	c net.Conn
}
func (e ErrNotMatched) Error() string {
	return fmt.Sprintf("mux: connection %v not matched by an matcher",
		e.c.RemoteAddr())
}
func (e ErrNotMatched) Temporary() bool { return true }
func (e ErrNotMatched) Timeout() bool { return false }
type errListenerClosed string
func (e errListenerClosed) Error() string   { return string(e) }
func (e errListenerClosed) Temporary() bool { return false }
func (e errListenerClosed) Timeout() bool   { return false }
var ErrListenerClosed = errListenerClosed("mux: listener closed")
func New(l net.Listener) CMux {
	return &cMux{
		root:   l,
		bufLen: 1024,
		errh:   func(_ error) bool { return true },
		donec:  make(chan struct{}),
	}
}
type CMux interface {
	Match(...Matcher) net.Listener
	Serve() error
	HandleError(ErrorHandler)
}
type matchersListener struct {
	ss []Matcher
	l  muxListener
}
type cMux struct {
	root   net.Listener
	bufLen int
	errh   ErrorHandler
	donec  chan struct{}
	sls    []matchersListener
}
func (m *cMux) Match(matchers ...Matcher) net.Listener {
	ml := muxListener{
		Listener: m.root,
		connc:    make(chan net.Conn, m.bufLen),
	}
	m.sls = append(m.sls, matchersListener{ss: matchers, l: ml})
	return ml
}
func (m *cMux) Serve() error {
	var wg sync.WaitGroup
	defer func() {
		close(m.donec)
		wg.Wait()
		for _, sl := range m.sls {
			close(sl.l.connc)
			for c := range sl.l.connc {
				_ = c.Close()
			}
		}
	}()
	for {
		c, err := m.root.Accept()
		if err != nil {
			if !m.handleErr(err) {
				return err
			}
			continue
		}
		wg.Add(1)
		go m.serve(c, m.donec, &wg)
	}
}
func (m *cMux) serve(c net.Conn, donec <-chan struct{}, wg *sync.WaitGroup) {
	defer wg.Done()
	muc := newMuxConn(c)
	for _, sl := range m.sls {
		for _, s := range sl.ss {
			matched := s(muc.getSniffer())
			if matched {
				select {
				case sl.l.connc <- muc:
				case <-donec:
					_ = c.Close()
				}
				return
			}
		}
	}
	_ = c.Close()
	err := ErrNotMatched{c: c}
	if !m.handleErr(err) {
		_ = m.root.Close()
	}
}
func (m *cMux) HandleError(h ErrorHandler) {
	m.errh = h
}
func (m *cMux) handleErr(err error) bool {
	if !m.errh(err) {
		return false
	}
	if ne, ok := err.(net.Error); ok {
		return ne.Temporary()
	}
	return false
}
type muxListener struct {
	net.Listener
	connc chan net.Conn
}
func (l muxListener) Accept() (net.Conn, error) {
	c, ok := <-l.connc
	if !ok {
		return nil, ErrListenerClosed
	}
	return c, nil
}
type MuxConn struct {
	net.Conn
	buf     bytes.Buffer
	sniffer bufferedReader
}
func newMuxConn(c net.Conn) *MuxConn {
	return &MuxConn{
		Conn: c,
	}
}