您非常接近解决方案 - 您唯一出错的地方是先从Conn
自身读取。你说得对,bufio.Reader
方法Peek
就是要走的路。诀窍是首先制作缓冲阅读器并调用Peek
缓冲阅读器,而不是从原始阅读器中读取Conn
。这是一种bufferedConn
可以满足您需要的类型:
type bufferedConn struct {
r *bufio.Reader
net.Conn // So that most methods are embedded
}
func newBufferedConn(c net.Conn) bufferedConn {
return bufferedConn{bufio.NewReader(c), c}
}
func newBufferedConnSize(c net.Conn, n int) bufferedConn {
return bufferedConn{bufio.NewReaderSize(c, n), c}
}
func (b bufferedConn) Peek(n int) ([]byte, error) {
return b.r.Peek(n)
}
func (b bufferedConn) Read(p []byte) (int, error) {
return b.r.Read(p)
}
它的作用是允许您访问所有普通net.Conn
方法(通过嵌入net.Conn
- 您也可以编写包装函数,但这更容易和更简洁),另外还提供对bufferedReader
'sPeek
和Read
方法的访问(重要的Read
是在 上调用bufferedReader
,而不是直接在 上调用,net.Conn
因为Peek
将数据存储在缓冲区中,因此后续调用Read
需要能够首先从该缓冲区中读取任何数据,然后再回退到底层net.Conn
)。
鉴于当前的默认缓冲区大小为 4096 字节,该newBufferedConnSize
函数可能是不必要的,但从技术上讲,如果您要依靠能够以Peek
给定大小调用并且不让它返回错误(特别是ErrBufferFull
),您应该明确设置它大小至少与您要查看的字节数一样大。
在Go Playground上查看。