//上数据结构,bytesBuffer typeBufferstruct{ buf[]byte//byte切片 offint//从&buf[off]地址读数据,从&buf[len(buf)]地址写数据 runeBytes[utf8.UTFMax]byte//avoidallocationofsliceoneachWriteByteorRune bootstrap[64]byte//memorytoholdfirstslice;helpssmallbuffers(Printf)avoidallocation. lastReadreadOp//lastreadoperation,sothatUnread*canworkcorrectly. }
再来看看我们bytes Buffer里面write是怎么实现的
func(b*Buffer)WriteString(sstring)(nint,errerror){ b.lastRead=opInvalid///Non-readoperation不需要读的标志等于0 m:=b.grow(len(s))//增长大小(准确来说是调整数据在buf中位置,也不一定增长),m当然是老数据末尾 returncopy(b.buf[m:],s),nil//copy一下数据,从m开始 }
最最重要的看过来
func(b*Buffer)grow(nint)int{ m:=b.Len()//func(b*Buffer)Len()int{returnlen(b.buf)-b.off} //m就是buf的len减去(-)b.off(读开始位置) ifm==0&&b.off!=0{ b.Truncate(0)//下面给予显示 } //调整大小和位置 iflen(b.buf)+n>cap(b.buf){ varbuf[]byte ifb.buf==nil&&n<=len(b.bootstrap){ buf=b.bootstrap[0:]//这个bootstrap缓存了buf的切片,说是防止重allocation }elseifm+n<=cap(b.buf)/2{//二倍申请新的slice的原则 copy(b.buf[:],b.buf[b.off:]) buf=b.buf[:m] }else{ //notenoughspaceanywhere buf=makeSlice(2*cap(b.buf)+n) copy(buf,b.buf[b.off:]) } b.buf=buf b.off=0 } b.buf=b.buf[0:b.off+m+n]//赋值咯 returnb.off+m }
func(b*Buffer)Truncate(nint){ b.lastRead=opInvalid switch{ casen<0||n>b.Len(): panic("bytes.Buffer:truncationoutofrange") casen==0: //Reusebufferspace. b.off=0 } b.buf=b.buf[0:b.off+n] }
makeSlice函数
funcmakeSlice(nint)[]byte{ //Ifthemakefails,giveaknownerror. deferfunc(){ ifrecover()!=nil{ panic(ErrTooLarge) } }() returnmake([]byte,n)//其实还是调用这个make }
最后看看一个使用示例咯
packagemain import( "bytes" "fmt" "strconv" "time" ) funcmain(){ varbufferbytes.Buffer ttime:=time.Now().UnixNano() fori:=0;i<10000000;i++{ buffer.WriteString(strconv.Itoa(i)) } ttime1:=time.Now().UnixNano() //取内容buffer.Bytes()或者buffer.String() fmt.Printf("timecal%f%d\n",float64(ttime1-ttime)/float64(1*time.Second),len(buffer.String())) }
总结:bytes buffer:就是写byte或者字符串string的一个容器