Go聖經-學習筆記入門bufio

來源:互聯網
上載者:User
這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。

bufio資料讀取注意項

在go聖經第一章節 bufio-緩衝IO,有個例子,不讀源碼不容易理解。

DEMO 1

func main(){    reader :=bufio.NewReader(    strings.NewReader(""http://studygolang.com. \nIt is the home of gophers, yes or no ?"),    )        line, _ := reader.ReadSlice('\n')    fmt.Printf("line=%s", line) // 注意點:bufio.ReadSlice會把'\n'讀取進來, 所以內建換行    n, _ := reader.ReadSlice('\n')    fmt.Printf("the line:%s\n", line) // 猜猜line返回結果    fmt.Println(string(n)) // 沒有讀取到分行符號    return}

列印結果:

the line:http://studygolang.com. the line:It is the home of gophersIt is the home of gophers, yes or no ?

DEMO 2

type Reader struct {     buf          []byte     rd           io.Reader // reader provided by the client     r, w         int       // buf read and write positions     err          error     lastByte     int     lastRuneSize int } func main(){    reader :=bufio.NewReader(    strings.NewReader(""http://studygolang.com. \nIt is the home of gophers, yes or no ?\n"),    ) // 多加一個`\n`        line, _ := reader.ReadSlice('\n')    fmt.Printf("line=%s", line) // 注意點:bufio.ReadSlice會把'\n'讀取進來, 所以內建換行    n, _ := reader.ReadSlice('\n')    fmt.Printf("the line:%s\n", line) // 猜猜line返回結果    fmt.Println(string(n)) // 讀取到分行符號    return}

列印結果:

the line:http://studygolang.com. the line:http://studygolang.com. It is the home of gophers, yes or no ?

其輸出結果對比,大跌眼鏡,居然有無\n結果,差距這麼大。

深入分析源碼:

func (b *Reader) ReadSlice(delim byte) (line []byte, err error){    for {        if i:=bytes.IndexBytes(b.buf[b.r:b.w], delim); i>= 0{            line = b.buf[b.r : b.r+i+1]            b.r =i+1            break        }        ...        b.fill() // 如果buf已經讀完,需要再次從b.rd中讀取新的資料    }}func (b *Reader) fill() {    if b.r > 0 {        copy(b.buf, b.buf[b.r: b:w])        b.w -=b.r        b.r=0    }        ...}

以上為代碼關鍵點,我們現在分別討論:

  • 對於第一個DEMO,第二個line返回的是It is the home of gophers, yes or no ?,期望是返回 http://studygolang.com..
    • 分析如下:因為第二次讀取reader.ReadSlice時,bytes.IndexByte沒有發現第二個\n, 所以返回的索引i小於0, 則會執行fill方法,則時因為第一次讀取了資料,所以b.r肯定大於0,所以執行了copy操作,buf底層數組發生了變化,變成了新寫入的b.buf[b.r: b.w]值,但是要注意,line的長度和容量是不變的,所以會存在截斷或者不足的情況。
  • 對於第二個DEMO,希望和期望的值是相同的
    • 分析如下:因為第二次讀取reader.ReadSlice時,bytes.IndexByte可以發現第二個\n, 則直接返回,寫沒有修改buf底層資料,也就使得line底層數組沒有發生變化。

結論:所以我們在使用標準庫時,不是很明白的方法要搞清楚才能好一些,不然容易犯錯誤。以下是規避ReadSlice錯誤的方法

func (b *Reader) ReadString(delim byte) (string, error) // 安全func (b *Reader) ReadBytes(delim byte) ([]byte, error) // 安全, 因為返回的[]byte是用make新分配記憶體空間

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.