加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

golang bytes buffer代码剖析

发布时间:2020-12-16 18:38:04 所属栏目:大数据 来源:网络整理
导读://上数据结构,bytesBuffertypeBufferstruct{buf[]byte//byte切片offint//从buf[off]地址读数据,从buf[len(buf)]地址写数据runeBytes[utf8.UTFMax]byte//avoidallocationofsliceoneachWriteByteorRunebootstrap[64]byte//memorytoholdfirstslice;helpssmallb
//上数据结构,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
}

再看看它用到过的函数Truncate函数,缩减切片

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%dn",float64(ttime1-ttime)/float64(1*time.Second),len(buffer.String()))

}

总结:bytes buffer:就是写byte或者字符串string的一个容器

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读