测试一下golang库函数里面bufio模块代码,Readline根据'\n'切分数据
packagemain import( "bytes" "errors" "fmt" "io" "time" ) typeReaderstruct{ buf[]byte rdio.Reader//readerprovidedbytheclient r,wint//bufreadandwritepositions errerror lastByteint lastRuneSizeint } constminReadBufferSize=16 constmaxConsecutiveEmptyReads=100 varerrNegativeRead=errors.New("bufio:readerreturnednegativecountfromRead") varErrBufferFull=errors.New("bufio:bufferfull") func(b*Reader)readErr()error{ err:=b.err b.err=nil returnerr } //fillreadsanewchunkintothebuffer. func(b*Reader)fill(){ //Slideexistingdatatobeginning. //fmt.Printf("readerr%v\n",b.r) ifb.r>0{ copy(b.buf,b.buf[b.r:b.w]) b.w-=b.r b.r=0 } ifb.w>=len(b.buf){ panic("bufio:triedtofillfullbuffer") } //Readnewdata:tryalimitednumberoftimes. //如果一直读取失败,则最多读取100次 fori:=maxConsecutiveEmptyReads;i>0;i--{ n,err:=b.rd.Read(b.buf[b.w:]) //fmt.Printf("count%v\n",n) ifn<0{ panic(errNegativeRead) } b.w+=n iferr!=nil{ b.err=err return } ifn>0{ return } } b.err=io.ErrNoProgress } func(b*Reader)Buffered()int{returnb.w-b.r} func(b*Reader)ReadSlice(delimbyte)(line[]byte,errerror){ for{ //Searchbuffer. //fmt.Printf("bytesindex%verr%v\n",bytes.IndexByte(b.buf[b.r:b.w],delim),b.err) ifi:=bytes.IndexByte(b.buf[b.r:b.w],delim);i>=0{ line=b.buf[b.r:b.r+i+1] //fmt.Printf("lineis%v\n",string(line)) b.r+=i+1 break } //Pendingerror? ifb.err!=nil{ line=b.buf[b.r:b.w] b.r=b.w err=b.readErr() break } //Bufferfull? //fmt.Printf("bufiobuffered%vlenbuf%v\n",b.Buffered(),len(b.buf)) ifb.Buffered()>=len(b.buf){ b.r=b.w line=b.buf err=ErrBufferFull break } b.fill()//bufferisnotfull } //Handlelastbyte,ifany. ifi:=len(line)-1;i>=0{ b.lastByte=int(line[i]) b.lastRuneSize=-1 } return } func(b*Reader)ReadLine()(line[]byte,isPrefixbool,errerror){ line,err=b.ReadSlice('\n') iferr==ErrBufferFull{ //Handlethecasewhere"\r\n"straddlesthebuffer. iflen(line)>0&&line[len(line)-1]=='\r'{ //Putthe'\r'backonbufanddropitfromline. //LetthenextcalltoReadLinecheckfor"\r\n". ifb.r==0{ //shouldbeunreachable panic("bufio:triedtorewindpaststartofbuffer") } b.r-- line=line[:len(line)-1] } returnline,true,nil } iflen(line)==0{ iferr!=nil{ line=nil } return } err=nil ifline[len(line)-1]=='\n'{ drop:=1 iflen(line)>1&&line[len(line)-2]=='\r'{ drop=2 } line=line[:len(line)-drop] } return } funcmain(){ reader:=bytes.NewReader([]byte("absc\r\nddd\n")) b:=&Reader{ buf:make([]byte,100),rd:reader,lastByte:-1,lastRuneSize:-1,} for{ line,isPrefix,err:=b.ReadLine() fmt.Printf("line%v/prefix%v/err%v\n",string(line),err) iferr==io.EOF{ break } time.Sleep(1*time.Second) } }
输出结果:
lineabsc/prefixfalse/err<nil> lineddd/prefixfalse/err<nil> line/prefixfalse/errEOF