groupcache源码分析5:byteview.go
byteview.go文件提供了一个数据结构ByteView,它是对[]byte或string类型的一个封装,提供了一些方法。
结构体定义,含有[]byte类型b和string类型s,优先使用b,b为nil再使用s。
type ByteView struct { b []byte s string }返回长度。
func (v ByteView) Len() int { if v.b != nil { return len(v.b) } return len(v.s) }基于结构体内容,返回一个[]byte类型。
func (v ByteView) ByteSlice() []byte { if v.b != nil { return cloneBytes(v.b) } return []byte(v.s) }基于结构体内容,返回一个string类型。
func (v ByteView) String() string { if v.b != nil { return string(v.b) } return v.s }返回数据中指定位置的原始字节。这里有一个小细节值得注意,那就是v.s[i]返回的是原始字节,而并不是如我们所想的返回字符串中某一个字符。
func (v ByteView) At(i int) byte { if v.b != nil { return v.b[i] } return v.s[i] }截取数据,返回的仍然是一个ByteView。
func (v ByteView) Slice(from, to int) ByteView { if v.b != nil { return ByteView{b: v.b[from:to]} } return ByteView{s: v.s[from:to]} }截取指定索引位置到结尾的数据,返回ByteView。
func (v ByteView) SliceFrom(from int) ByteView { if v.b != nil { return ByteView{b: v.b[from:]} } return ByteView{s: v.s[from:]} }拷贝数据到一个[]byte变量中。
func (v ByteView) Copy(dest []byte) int { if v.b != nil { return copy(dest, v.b) } return copy(dest, v.s) }两个ByteView做比较。
func (v ByteView) Equal(b2 ByteView) bool { if b2.b == nil { return v.EqualString(b2.s) } return v.EqualBytes(b2.b) }与字符串做比较,如果v的b为空,那么直接拿string类型s判断是否相等即可。否则,需要拿[]byte类型b和string比较,先判断长度是否相等,再逐个字节比对。
func (v ByteView) EqualString(s string) bool { if v.b == nil { return v.s == s } l := v.Len() if len(s) != l { return false } for i, bi := range v.b { if bi != s[i] { return false } } return true }与上一个方法类似,只不过是与[]byte的比较。
func (v ByteView) EqualBytes(b2 []byte) bool { if v.b != nil { return bytes.Equal(v.b, b2) } l := v.Len() if len(b2) != l { return false } for i, bi := range b2 { if bi != v.s[i] { return false } } return true }调用NewReader方法返回io.ReadSeeker类型。
func (v ByteView) Reader() io.ReadSeeker { if v.b != nil { return bytes.NewReader(v.b) } return strings.NewReader(v.s) }从ByteView指定位置读取数据拷贝到[]byte中。
func (v ByteView) ReadAt(p []byte, off int64) (n int, err error) { if off < 0 { return 0, errors.New("view: invalid offset") } if off >= int64(v.Len()) { return 0, io.EOF } n = v.SliceFrom(int(off)).Copy(p) if n < len(p) { err = io.EOF } return }读取数据写入到ByteView中。
func (v ByteView) WriteTo(w io.Writer) (n int64, err error) { var m int if v.b != nil { m, err = w.Write(v.b) } else { m, err = io.WriteString(w, v.s) } if err == nil && m < v.Len() { err = io.ErrShortWrite } n = int64(m) return }