亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

掃描儀提前終止

掃描儀提前終止

Go
開滿天機 2021-07-01 14:00:57
我正在嘗試在 Go 中編寫一個掃描儀,它掃描連續行并在返回之前清理該行,以便您可以返回邏輯行。因此,給定以下 SplitLine 函數 ( Play ):func ScanLogicalLines(data []byte, atEOF bool) (int, []byte, error) {    if atEOF && len(data) == 0 {        return 0, nil, nil    }    i := bytes.IndexByte(data, '\n')    for i > 0 && data[i-1] == '\\' {        fmt.Printf("i: %d, data[i] = %q\n", i, data[i])        i = i + bytes.IndexByte(data[i+1:], '\n')    }    var match []byte = nil    advance := 0    switch {    case i >= 0:        advance, match = i + 1, data[0:i]    case atEOF:         advance, match = len(data), data    }    token := bytes.Replace(match, []byte("\\\n"), []byte(""), -1)    return advance, token, nil}func main() {    simple := `Just a test.See what is returned. \when you have empty lines.Followed by a newline.`    scanner := bufio.NewScanner(strings.NewReader(simple))    scanner.Split(ScanLogicalLines)    for scanner.Scan() {        fmt.Printf("line: %q\n", scanner.Text())    }}我希望代碼返回如下內容:line: "Just a test."line: ""line: "See what is returned, when you have empty lines."line: ""line: "Followed by a newline."但是,它在返回第一行后停止。第二次調用 return 1, "", nil。任何人有任何想法,還是一個錯誤?
查看完整描述

1 回答

?
精慕HU

TA貢獻1845條經驗 獲得超8個贊

我認為這是一個錯誤,因為提前值 > 0 并不打算進行進一步的讀取調用,即使返回的令牌為零(bufio.SplitFunc):

如果數據還沒有一個完整的標記,例如如果它在掃描行時沒有換行符,SplitFunc 可以返回 (0, nil) 以通知掃描器將更多數據讀入切片并再次嘗試使用更長的切片從輸入中的相同點。

這是怎么回事

輸入緩沖區bufio.Scanner默認為 4096 字節。這意味著如果可以,它會立即讀取到這個數量,然后執行 split 函數。在您的情況下,掃描儀可以一次讀取您的所有輸入,因為它遠低于 4096 字節。這意味著下一次讀取它將導致EOF這里的主要問題。

一步步

  1. scanner.Scan 讀取您的所有數據

  2. 你得到了那里的所有文本

  3. 你尋找一個令牌,你找到第一個換行符,它只有一個換行符

  4. nil通過從匹配中刪除換行符作為令牌返回

  5. scanner.Scan 假設:用戶需要更多數據

  6. scanner.Scan 嘗試閱讀更多

  7. EOF 發生

  8. scanner.Scan 嘗試標記最后一次

  9. 你發現 "Just a test."

  10. scanner.Scan 嘗試標記最后一次

  11. 你尋找一個標記,你會發現第三行只有一個換行符

  12. nil通過從匹配中刪除換行符作為令牌返回

  13. scanner.Scan看到nil令牌并設置錯誤 ( EOF)

  14. 執行結束

如何規避

任何非零的令牌都會阻止這種情況。只要您返回非 nil 令牌,掃描器就不會檢查EOF并繼續執行您的令牌生成器。

您的代碼返回nil令牌的原因是在無事可做bytes.Replace返回 。. 您可以通過返回一個有容量但沒有元素的切片來防止這種情況,因為這將是非 nil: 。nilappend([]byte(nil), nil...) == nilmake([]byte, 0, 1) != nil


查看完整回答
反對 回復 2021-07-12
  • 1 回答
  • 0 關注
  • 238 瀏覽
慕課專欄
更多

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號