aspcms做双语网站修改配置,网站建设要知道的,做个网站大约多少钱,旅游网站建设首选赢旅动力#x1f680; 优质资源分享 #x1f680;
学习路线指引#xff08;点击解锁#xff09;知识定位人群定位#x1f9e1; Python实战微信订餐小程序 #x1f9e1;进阶级本课程是python flask微信小程序的完美结合#xff0c;从项目搭建到腾讯云部署上线#xff0c;打造一… 优质资源分享
学习路线指引点击解锁知识定位人群定位 Python实战微信订餐小程序 进阶级本课程是python flask微信小程序的完美结合从项目搭建到腾讯云部署上线打造一个全栈订餐系统。Python量化交易实战入门级手把手带你打造一个易扩展、更安全、效率更高的量化交易系统
golang bufio
目录* golang bufio 使用bufio进行写 - 缓存中满数据 - 缓存中仍有空间 - 待写入的数据大于缓存的大小 - 缓存重用 - 获取缓存的可用空间数 使用bufio进行读 - Peek - Read - ReadSlice - ReadLine - ReadBytes - Scanner 附 - 并发复用缓存 - 限制从io.Reader中读取的数据量 * 方式1 * 方式2 参考
当频繁地对少量数据读写时会占用IO造成性能问题。golang的bufio库使用缓存来一次性进行大块数据的读写以此降低IO系统调用提升性能。
在Transport中可以设置一个名为WriteBufferSize的参数该参数指定了底层(Transport.dialConn)写buffer的大小。 tr : http.Transport{WriteBufferSize: 64 * 1024,} pconn.br bufio.NewReaderSize(pconn, t.readBufferSize())pconn.bw bufio.NewWriterSize(persistConnWriter{pconn}, t.writeBufferSize())
使用bufio进行写
可以使用bufio.NewWriter初始化一个大小为4096字节的Writer(见下)或使用bufio.NewWriterSize初始化一个指定大小的Writer。
Writer中的主要参数为缓存区buf缓存区中的数据偏移量n以及写入接口wr
type Writer struct {err errorbuf []byten intwr io.Writer
}
bufio.Writer方法可以一次性写入缓存中的数据通常有如下三种情况
缓存中满数据缓存中仍有空间待写入的数据大于缓存的大小
缓存中满数据
当缓存中满数据时会执行写操作。
缓存中仍有空间
如果缓存中仍有数据则不会执行写入动作除非调用Flush()方法。
待写入的数据大于缓存的大小
由于此时缓存无法缓存足够的数据此时会跳过缓存直接执行写操作
type Writer intfunc (*Writer) Write(p []byte) (n int, err error) {fmt.Printf(Writing: %s\n, p)return len(p), nil
}func main() {w : new(Writer)bw1 : bufio.NewWriterSize(w, 4)// Case 1: Writing to buffer until fullbw1.Write([]byte{1})bw1.Write([]byte{2})bw1.Write([]byte{3})bw1.Write([]byte{4}) // write - buffer is full// Case 2: Buffer has spacebw1.Write([]byte{5}) //此时buffer中无法容纳更多的数据执行写操作写入 []byte{1,2,3,4}err bw1.Flush() // forcefully write remainingif err ! nil {panic(err)}// Case 3: (too) large write for buffer// Will skip buffer and write directlybw1.Write([]byte(12345)) //buffer不足直接执行写操作
}//结果
Writing: 1234
Writing: 5
Writing: 12345
缓存重用
申请缓存对性能是有损耗的可以使用Reset方法重置缓存其内部只是将Writer的数据偏移量n置0。
wr : new(Writer)
bw : bufio.NewWriterSize(wr,2)
bw.Reset(wr)
获取缓存的可用空间数
Available()方法可以返回缓存的可用空间数即len(Writer.buf)-Writer.n
使用bufio进行读
与用于写数据的Writer类似读数据也有一个Reader可以使用NewReader初始化一个大小为4096字节的Reader或使用NewReaderSize初始化一个指定大小的Reader(要求最小字节为16)。Reader也有一个记录偏移量的变量r
type Reader struct {buf []byterd io.Reader // reader provided by the clientr, w int // buf read and write positionserr errorlastByte int // last byte read for UnreadByte; -1 means invalidlastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}
Peek
该方法会返回buf中的前n个字节的内容但与Read操作不同的是它不会消费缓存中的数据即不会增加数据偏移量因此通常也会用于判断是否读取结束(EOF)。通常有如下几种情况
如果peak的值小于缓存大小则返回相应的内容如果peak的值大于缓存大小则返回bufio.ErrBufferFull错误如果peak的值包含EOF且小于缓存大小则返回EOF
Read
将数据读取到p涉及将数据从缓存拷贝到p。
func (b *Reader) Read(p []byte) (n int, err error)
ReadSlice
该方法会读从缓存读取数据直到遇到第一个delim。如果缓存中没有delim则返回EOF如果查询的长度超过了缓存大小则返回 io.ErrBufferFull 错误。
func (b *Reader) ReadSlice(delim byte) (line []byte, err error)
例如delim为,则下面会返回的内容为1234,。
func main() {r : strings.NewReader(1234,567)rb : bufio.NewReaderSize(r, 20)fmt.Println(rb.ReadSlice(,))
}// 结果[49 50 51 52 44] 注意ReadSlice返回的是原始缓存中的内容如果针对缓存作并发操作则返回的内容有可能被其他操作覆盖。因此在官方注释里面有写建议使用ReadBytes或ReadString。但ReadBytes和ReadString涉及内存申请和拷贝因此会影响性能。在追求高性能的场景下建议外部使用sync.pool来提供缓存。 // Because the data returned from ReadSlice will be overwritten
// by the next I/O operation, most clients should use
// ReadBytes or ReadString instead. ReadLine
ReadLine() (line []byte, isPrefix bool, err error)
ReadLine底层用到了ReadSlice但在返回时会移除\n 或\r\n。需要注意的是如果切片中没有找到换行符则不会返回EOF或io.ErrBufferFull 错误相反它会将isPrefix置为true
ReadBytes
与ReadSlice类似但它会返回一个新的切片因此便于并发使用。如果找不到delimReadBytes会返回io.EOF
func (b *Reader) ReadBytes(delim byte) ([]byte, error)
Scanner
scanner可以不断将数据读取到缓存(默认64*1024字节)。
func main() {rb : strings.NewReader(12345678901234567890)scanner : bufio.NewScanner(rb)for scanner.Scan() {fmt.Printf(Token (Scanner): %q\n, scanner.Text())}
}// 结果Token (Scanner): 12345678901234567890
附
并发复用缓存
io.bufio支持缓存读写以及Reset操作但在并发复用缓存方面做的不是很好可以参考victoriaMetrics之byteBuffer。 无需并发复用的话用io.bufio即可。 限制从io.Reader中读取的数据量
方式1
使用io.LimitReader来限制从Reader中读取的数据量LimitedReader.N给出了可读取的剩余数据量。一旦N变为0即时Reader中仍然有数据此时也会返回EOF
type LimitedReader struct {R Reader // underlying readerN int64 // max bytes remaining
}
func main() {rb : strings.NewReader(12345678901234567890)lr : io.LimitReader(rb, 3)//限制可以读取3个字节的数据buf : make([]byte, 400)fmt.Println(lr.Read(buf)) //达到读取上限制LimitedReader.N0fmt.Println(lr.Read(buf)) //此时返回EOF
}//结果
3 nil
0 EOF
方式2
可以使用io.CopyN限制从Reader读取的数据量它内部也使用了io.LimitReader但支持多次读取。
type Writer intfunc (*Writer) Write(p []byte) (n int, err error) {fmt.Printf(Writing: %s\n, p)return len(p), nil
}func main() {rb : strings.NewReader(12345678901234567890)w : new(Writer)fmt.Println(io.CopyN(w, rb, 6))fmt.Println(io.CopyN(w, rb, 6))
}//结果
Writing: 123456
6 nil
Writing: 789012
6 nil
参考
how-to-read-and-write-with-golang-bufio