golang 环形缓冲区 Reader Wirter Circle Buffer

package main

import (
	"errors"
	"fmt"
	"io"
	"time"
)

type CircleByteBuffer struct {
	io.Reader
	io.Writer
	io.Closer
	datas []byte

	start int
	end int
	size int
	isClose bool
	isEnd bool
}

func NewCircleByteBuffer(len int)*CircleByteBuffer{
	var e=new(CircleByteBuffer)
	e.datas=make([]byte,len)
	e.start=0
	e.end=0
	e.size=len
	e.isClose=false
	e.isEnd=false
	return e
}

func (e*CircleByteBuffer)getLen()int{
	if e.start==e.end{
		return 0
	}else if e.start<e.end{
		return e.end-e.start
	}else{
		return e.start-e.end
	}
}
func (e*CircleByteBuffer)getFree()int{
	return e.size-e.getLen()
}
func (e*CircleByteBuffer)putByte(b byte)error{
	if e.isClose{return io.EOF}
	e.datas[e.end]=b
	var pos=e.end+1
	for pos==e.start{
		if e.isClose{return io.EOF}
		time.Sleep(time.Microsecond)
	}
	if pos==e.size {
		e.end = 0
	}else {
		e.end = pos
	}
	return nil
}

func (e*CircleByteBuffer)getByte()(byte,error){
	if e.isClose{return 0, io.EOF}
	if e.isEnd&&e.getLen()<=0{return 0, io.EOF}
	if e.getLen()<=0 {return 0,errors.New("no datas")}
	var ret=e.datas[e.start]
	e.start++
	if e.start==e.size {
		e.start = 0
	}
	return ret,nil
}
func (e*CircleByteBuffer)geti(i int)byte{
	if i>=e.getLen() {
		panic("out buffer")
	}
	var pos=e.start+i
	if pos>=e.size {
		pos -= e.size
	}
	return e.datas[pos]
}

/*func (e*CircleByteBuffer)puts(bts []byte){
	for i:=0;i<len(bts);i++{
		e.put(bts[i])
	}
}
func (e*CircleByteBuffer)gets(bts []byte)int{
	if bts==nil {return 0}
	var ret=0
	for i:=0;i<len(bts);i++{
		if e.getLen()<=0{break}
		bts[i]=e.get()
		ret++
	}
	return ret
}*/
func (e*CircleByteBuffer)Close() error{
	e.isClose=true
	return nil
}
func (e*CircleByteBuffer)Read(bts []byte)(int,error){
	if e.isClose{return 0, io.EOF}
	if bts==nil {return 0,errors.New("bts is nil")}
	var ret=0
	for i:=0;i<len(bts);i++{
		b,err:=e.getByte()
		if err!=nil{
			if err==io.EOF{
				return ret, err
			}
			return ret, nil
		}
		bts[i]=b
		ret++
	}
	if e.isClose{return ret, io.EOF}
	return ret,nil
}
func (e*CircleByteBuffer)Write(bts []byte)(int,error){
	if e.isClose{return 0, io.EOF}
	if bts==nil {
		e.isEnd=true
		return 0,io.EOF
	}
	var ret=0
	for i:=0;i<len(bts);i++{
		err:=e.putByte(bts[i])
		if err!=nil{
			fmt.Println("Write bts err:",err)
			return ret,err
		}
		ret++
	}
	if e.isClose{return ret, io.EOF}
	return ret,nil
}

 

双线程安全,示例:

func main() {
	fmt.Println("hello world")
	b:=NewCircleByteBuffer(1024)
	go func(){
		for i:=0;i<10;i++ {
			bts:=[]byte{byte(i)}
			b.Write(bts)
			time.Sleep(time.Second)
		}
		fmt.Println("Close!")
		b.Close()
	}()

	buf:=make([]byte,512)
	for{
		n,err:=b.Read(buf)
		if n>0{
			fmt.Println("Reads:",buf[0:n])
		}
		if err!=nil{
			break
		}
	}
	fmt.Println("end!")
}

输出:

hello world
Reads: [0]
Reads: [1]
Reads: [2]
Reads: [3]
Reads: [4]
Reads: [5]
Reads: [6]
Reads: [7]
Reads: [8]
Reads: [9]
Close!
end!

 

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值