1. 程式人生 > 其它 >golang標準庫學習———bytes.Buffer

golang標準庫學習———bytes.Buffer

轉自:Golang bytes.buffer詳解 - salami-china - 部落格園 (cnblogs.com) 


Buffer 是 bytes 包中的一個 type Buffer struct{…}

(是一個變長的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一個 空的 buffer,但是可以使用)
Buffer 就像一個集裝箱容器,可以存東西,取東西(存取資料)

 

建立緩衝器

func main() {
    buf1 := bytes.NewBufferString("hello")
    buf2 := bytes.NewBuffer([]byte("hello"))
    buf3 := bytes.NewBuffer([]byte{'h','e','l','l','o'})
    fmt.Printf("%v,%v,%v\n",buf1,buf2,buf3)
    fmt.Printf("%v,%v,%v\n",buf1.Bytes(),buf2.Bytes(),buf3.Bytes())

    buf4 := bytes.NewBufferString("")
    buf5 := bytes.NewBuffer([]byte{})
    fmt.Println(buf4.Bytes(),buf5.Bytes())
}

  輸出

hello,hello,hello
[104 101 108 108 111],[104 101 108 108 111],[104 101 108 108 111]
[] []

  

寫入到緩衝器
buffer在new的時候是空的,也是可以直接Write的

Write

func (b *Buffer) Write(p []byte) (n int,err error)

  

func main() {
s := []byte(" world")
buf := bytes.NewBufferString("hello")
fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
buf.Write(s)
fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
}

  結果

hello,[104 101 108 108 111]
hello world,[104 101 108 108 111 32 119 111 114 108 100]

  WriteString

func (b *Buffer) WriteString(s string)(n int,err error)

  

func main() {
    s := " world"
    buf := bytes.NewBufferString("hello")
    fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
    buf.WriteString(s)
    fmt.Printf("%v,%v\n",buf.String(),buf.Bytes())
}

  結果

hello,[104 101 108 108 111]
hello world,[104 101 108 108 111 32 119 111 114 108 100]

  

緩衝區原理介紹
go位元組緩衝區底層以位元組切片做儲存,切片存在長度 len 與容量 cap, 緩衝區寫從長度len的位置開始寫,當len>cap時,會自動擴容。緩衝區讀會從內建標記off位置開始讀(off始終記錄讀的起始位置),當off==len時,表明緩衝區已全部讀完
並重置緩衝區(len=off=0),此外當將要內容長度+已寫的長度(即len) <= cap/2時,緩衝區前移覆蓋掉已讀的內容(off=0,len-=off),從避免緩衝區不斷擴容

func main() {
    byteSlice := make([]byte, 20) 
    byteSlice[0] = 1                                  // 將緩衝區第一個位元組置1
    byteBuffer := bytes.NewBuffer(byteSlice)          // 建立20位元組緩衝區 len = 20 off = 0
    c, _ := byteBuffer.ReadByte()                     // off+=1
    fmt.Printf("len:%d, c=%d\n", byteBuffer.Len(), c) // len = 20 off =1   列印c=1
    byteBuffer.Reset()                                // len = 0 off = 0
    fmt.Printf("len:%d\n", byteBuffer.Len())          // 列印len=0
    byteBuffer.Write([]byte("hello byte buffer"))     // 寫緩衝區  len+=17
    fmt.Printf("len:%d\n", byteBuffer.Len())          // 列印len=17
    byteBuffer.Next(4)                                // 跳過4個位元組 off+=4
    c, _ = byteBuffer.ReadByte()                      // 讀第5個位元組 off+=1
    fmt.Printf("第5個位元組:%d\n", c)                    // 列印:111(對應字母o)    len=17 off=5
    byteBuffer.Truncate(3)                            // 將未位元組數置為3        len=off+3=8   off=5
    fmt.Printf("len:%d\n", byteBuffer.Len())          // 列印len=3為未讀位元組數  上面len=8是底層切片長度
    byteBuffer.WriteByte(96)                          // len+=1=9 將y改成A
    byteBuffer.Next(3)                                // len=9 off+=3=8
    c, _ = byteBuffer.ReadByte()                      // off+=1=9    c=96
    fmt.Printf("第9個位元組:%d\n", c)                    // 列印:96
}

  demo1

package main

import "bytes"
import "log"

func main(){
    buf := &bytes.Buffer{}
    buf.WriteString("abcdefg")

    str, _ := buf.ReadString('?')
    log.Println("str = ", str)
    log.Println("buff = ", buf.String())
}

  輸出 

[root@localhost]# go run buffer.go 
2020/06/05 19:12:42 str =  abcdefg
2020/06/05 19:12:42 buff = 

   demo2

// MyBuffer2 project main.go
package main

import (
    "bytes"
    "log"
    "os"
)

func main() {
    log.SetFlags(log.Lshortfile)
    buff := bytes.NewBufferString("123456789")
    log.Println("buff = ", buff.String())

    s := make([]byte, 4)
    n, _ := buff.Read(s)
    log.Println("buff = ", buff.String())
    log.Println("s = ", string(s))
    log.Println("n = ", n)

    n, _ = buff.Read(s)
    log.Println("buff = ", buff.String())
    log.Println("s = ", string(s))
    log.Println("n = ", n)

    n, _ = buff.Read(s)
    log.Println("buff = ", buff.String())
    log.Println("s = ", string(s))
    log.Println("n = ", n)

    buff.Reset()
    buff.WriteString("abcdefg")
    log.Println("buff = ", buff.String())

    b, _ := buff.ReadByte()
    log.Println("b = ", string(b))
    log.Println("buff = ", buff.String())

    b, _ = buff.ReadByte()
    log.Println("b = ", string(b))
    log.Println("buff = ", buff.String())

    bs, _ := buff.ReadBytes('e')
    log.Println("bs = ", string(bs))
    log.Println("buff = ", buff.String())

    buff.Reset()
    buff.WriteString("編譯輸出GO")
    r, l, _ := buff.ReadRune()
    log.Println("r = ", r, ", l = ", l, ", string(r) = ", string(r))

    buff.Reset()
    buff.WriteString("qwer")
    str, _ := buff.ReadString('?')
    log.Println("str = ", str)
    log.Println("buff = ", buff.String())

    buff.WriteString("qwer")
    str, _ = buff.ReadString('w')
    log.Println("str = ", str)
    log.Println("buff = ", buff.String())

    file, _ := os.Open("doc.go")
    buff.Reset()
    buff.ReadFrom(file)
    log.Println("doc.go = ", buff.String())

    buff.Reset()
    buff.WriteString("中國人")
    cbyte := buff.Bytes()
    log.Println("cbyte = ", cbyte)
}

  輸出:

C:/Go/bin/go.exe build -i [D:/golang/src/MyBuffer2]
成功: 程序退出程式碼 0.
D:/golang/src/MyBuffer2/MyBuffer2.exe  [D:/golang/src/MyBuffer2]
main.go:13: buff =  123456789
main.go:17: buff =  56789
main.go:18: s =  1234
main.go:19: n =  4
main.go:22: buff =  9
main.go:23: s =  5678
main.go:24: n =  4
main.go:27: buff =  
main.go:28: s =  9678
main.go:29: n =  1
main.go:33: buff =  abcdefg
main.go:36: b =  a
main.go:37: buff =  bcdefg
main.go:40: b =  b
main.go:41: buff =  cdefg
main.go:44: bs =  cde
main.go:45: buff =  fg
main.go:50: r =  32534 , l =  3 , string(r) =  編
main.go:55: str =  qwer
main.go:56: buff =  
main.go:60: str =  qw
main.go:61: buff =  er
main.go:66: doc.go =  // MyBuffer2 project doc.go

/*
MyBuffer2 document
*/
package main

main.go:71: cbyte =  [228 184 173 229 155 189 228 186 186]
成功: 程序退出程式碼 0.