最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

golang中bufio.SplitFunc的深入理解

 更新時間:2018年10月14日 15:58:48   作者:goland  
這篇文章主要給大家介紹了關(guān)于golang中bufio.SplitFunc的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對大家學(xué)習(xí)或者使用golang具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧

前言

bufio模塊是golang標(biāo)準(zhǔn)庫中的模塊之一,主要是實現(xiàn)了一個讀寫的緩存,用于對數(shù)據(jù)的讀取或者寫入操作。該模塊在多個涉及io的標(biāo)準(zhǔn)庫中被使用,比如http模塊中使用buffio來完成網(wǎng)絡(luò)數(shù)據(jù)的讀寫,壓縮文件的zip模塊利用bufio來操作文件數(shù)據(jù)的讀寫等。

golang的bufio包里面定以的SplitFunc是一個比較重要也比較難以理解的東西,本文希望通過結(jié)合簡單的實例介紹SplitFunc的工作原理以及如何實現(xiàn)一個自己的SplitFunc。

一個例子

在bufio包里面定義了一些常用的工具比如Scanner,你可能需要讀取用戶在標(biāo)準(zhǔn)輸入里面輸入的一些東西,比如我們做一個復(fù)讀機,讀取用戶的每一行輸入,然后打印出來:

package main
import (
 "bufio"
 "fmt"
 "os"
)
func main() {
 scanner := bufio.NewScanner(os.Stdin)
 scanner.Split(bufio.ScanLines)
 for scanner.Scan() {
 fmt.Println(scanner.Text())
 }
}

這個程序很簡單,os.Stdin實現(xiàn)了io.Reader接口,我們從這個reader創(chuàng)建了一個scanner,設(shè)置分割函數(shù)為bufio.ScanLines,然后for循環(huán),每次讀到一行數(shù)據(jù)就將文本內(nèi)容打印出來。麻雀雖小五臟俱全,這個小程序雖然簡單,卻引出了我們今天要介紹的對象: bufio.SplitFunc,它的定義是這個樣子的:

package "buffio"
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

golang官方文檔的描述是這個樣子的:

SplitFunc is the signature of the split function used to tokenize the input. The arguments are an initial substring of the remaining unprocessed data and a flag, atEOF, that reports whether the Reader has no more data to give. The return values are the number of bytes to advance the input and the next token to return to the user, if any, plus an error, if any.

Scanning stops if the function returns an error, in which case some of the input may be discarded.

Otherwise, the Scanner advances the input. If the token is not nil, the Scanner returns it to the user. If the token is nil, the Scanner reads more data and continues scanning; if there is no more data--if atEOF was true--the Scanner returns. If the data does not yet hold a complete token, for instance if it has no newline while scanning lines, a SplitFunc can return (0, nil, nil) to signal the Scanner to read more data into the slice and try again with a longer slice starting at the same point in the input.

The function is never called with an empty data slice unless atEOF is true. If atEOF is true, however, data may be non-empty and, as always, holds unprocessed text.

英文!參數(shù)這么多!返回值這么多!好煩!不知道各位讀者遇到這種文檔會不會有這種感覺...正式由于這種情況,我才決定寫一篇文章介紹一下SplitFunc的具體工作原理,用一種通俗的方式結(jié)合具體實例加以說明,希望對讀者有所幫助。
好了,廢話少說,開始正題吧!

Scanner和SplitFunc的工作機制

package "buffio"
type SplitFunc func(data []byte, atEOF bool) (advance int, token []byte, err error)

Scanner是有緩存的,意思是Scanner底層維護(hù)了一個Slice用來保存已經(jīng)從Reader中讀取的數(shù)據(jù),Scanner會調(diào)用我們設(shè)置SplitFunc,將緩沖區(qū)內(nèi)容(data)和是否已經(jīng)輸入完了(atEOF)以參數(shù)的形式傳遞給SplitFunc,而SplitFunc的職責(zé)就是根據(jù)上述的兩個參數(shù)返回下一次Scan需要前進(jìn)幾個字節(jié)(advance),分割出來的數(shù)據(jù)(token),以及錯誤(err)。

這是一個通信雙向的過程,Scanner告訴我們的SplitFunc已經(jīng)掃描到的數(shù)據(jù)和是否到結(jié)尾了,我們的SplitFunc則根據(jù)這些信息將分割的結(jié)果返回和下次掃描需要前進(jìn)的位置返回給Scanner。用一個例子來說明:

package main
import (
 "bufio"
 "fmt"
 "strings"
)
func main() {
 input := "abcdefghijkl"
 scanner := bufio.NewScanner(strings.NewReader(input))
 split := func(data []byte, atEOF bool) (advance int, token []byte, err error) {
  fmt.Printf("%t\t%d\t%s\n", atEOF, len(data), data)
  return 0, nil, nil
 }
 scanner.Split(split)
 buf := make([]byte, 2)
 scanner.Buffer(buf, bufio.MaxScanTokenSize)
 for scanner.Scan() {
  fmt.Printf("%s\n", scanner.Text())
 }
}

輸出

false 2 ab
false 4 abcd
false 8 abcdefgh
false 12 abcdefghijkl
true 12 abcdefghijkl

這里我們把緩沖區(qū)的初始大小設(shè)置為了2,不夠的時候會擴展為原來的2倍,最大為bufio.MaxScanTokenSize,這樣一開始掃描2個字節(jié),我們的緩沖區(qū)就滿了,reader的內(nèi)容還沒有讀取到EOF,然后split函數(shù)執(zhí)行,輸出:

false 2 ab

緊接著函數(shù)返回 0, nil, nil這個返回值告訴Scanner數(shù)據(jù)不夠,下次讀取的位置前進(jìn)0位,需要繼續(xù)從reader里面讀取,此時因為緩沖區(qū)滿了,所以容量擴展為2 * 2 = 4,reader的內(nèi)容還沒有讀取到EOF,輸出

false 4 abcd

重復(fù)上述步驟,一直到最后全部內(nèi)容讀取完了,EOF此時變成了true

true 12 abcdefghijkl

看了上面的過程是不是對SplitFunc的工作原來有了一點理解了呢?再回頭看一下golang的官方文檔有沒有覺得稍微理解了一點?下面是bufio.ScanLines的實現(xiàn),讀者可以自己研究一下該函數(shù)是如何工作的

標(biāo)準(zhǔn)庫里的ScanLines

func ScanLines(data []byte, atEOF bool) (advance int, token []byte, err error) {
 // 表示我們已經(jīng)掃描到結(jié)尾了
 if atEOF && len(data) == 0 {
  return 0, nil, nil
 }
 // 找到\n的位置
 if i := bytes.IndexByte(data, '\n'); i >= 0 {
  // 把下次開始讀取的位置向前移動i + 1位
  return i + 1, dropCR(data[0:i]), nil
 }
 // 這里處理的reader內(nèi)容全部讀取完了,但是內(nèi)容不為空,所以需要把剩余的數(shù)據(jù)返回
 if atEOF {
  return len(data), dropCR(data), nil
 }
 // 表示現(xiàn)在不能分割,向Reader請求更多的數(shù)據(jù)
 return 0, nil, nil
}

參考

In-depth introduction to bufio.Scanner in Golang

總結(jié)

以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,如果有疑問大家可以留言交流,謝謝大家對腳本之家的支持。

相關(guān)文章

  • 從零封裝Gin框架實現(xiàn)日志初始化及切割歸檔功能

    從零封裝Gin框架實現(xiàn)日志初始化及切割歸檔功能

    這篇文章主要為大家介紹了從零封裝Gin框架實現(xiàn)日志初始化及切割歸檔功能示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Go語言LeetCode題解1046最后一塊石頭的重量

    Go語言LeetCode題解1046最后一塊石頭的重量

    這篇文章主要為大家介紹了Go語言LeetCode題解1046最后一塊石頭的重量,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-12-12
  • Golang中的強大Web框架Fiber詳解

    Golang中的強大Web框架Fiber詳解

    在不斷發(fā)展的Web開發(fā)領(lǐng)域中,選擇正確的框架可以極大地影響項目的效率和成功,介紹一下Fiber,這是一款令人印象深刻的Golang(Go語言)Web框架,在本文中,我們將深入了解Fiber的世界,探討其獨特的特性,并理解為什么它在Go生態(tài)系統(tǒng)中引起了如此大的關(guān)注
    2023-10-10
  • Go語言的Windows下環(huán)境配置以及簡單的程序結(jié)構(gòu)講解

    Go語言的Windows下環(huán)境配置以及簡單的程序結(jié)構(gòu)講解

    這篇文章主要介紹了Go語言的Windows下環(huán)境配置以及簡單的程序結(jié)構(gòu)講解,從編程語言約定俗成的hellow world開始,需要的朋友可以參考下
    2015-10-10
  • golang協(xié)程池設(shè)計詳解

    golang協(xié)程池設(shè)計詳解

    這篇文章主要介紹了golang協(xié)程池設(shè)計詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-09-09
  • Go語言中的指針運算實例分析

    Go語言中的指針運算實例分析

    這篇文章主要介紹了Go語言中的指針運算技巧,實例分析了Go語言指針運算的實現(xiàn)方法,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • Go 防止 goroutine 泄露的方法

    Go 防止 goroutine 泄露的方法

    Go 的并發(fā)模型與其他語言不同,雖說它簡化了并發(fā)程序的開發(fā)難度,但如果不了解使用方法,常常會遇到 goroutine 泄露的問題。本篇主要從如何寫出正確代碼的角度來介紹如何防止 goroutine 的泄露,需要的朋友可以參考下
    2019-09-09
  • Go語言使用defer+recover解決panic導(dǎo)致程序崩潰的問題

    Go語言使用defer+recover解決panic導(dǎo)致程序崩潰的問題

    如果協(xié)程出現(xiàn)了panic,就會造成程序的崩潰,這時可以在goroutine中使用recover來捕獲panic,進(jìn)行處理,本文就詳細(xì)的介紹一下,感興趣的可以了解一下
    2021-09-09
  • Golang使用zlib壓縮和解壓縮字符串

    Golang使用zlib壓縮和解壓縮字符串

    本文給大家分享的是Golang使用zlib壓縮和解壓縮字符串的方法和示例,有需要的小伙伴可以參考下
    2017-02-02
  • Go語言字符串基礎(chǔ)示例詳解

    Go語言字符串基礎(chǔ)示例詳解

    這篇文章主要為大家介紹了Go語言字符串基礎(chǔ)的示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2021-11-11

最新評論

望奎县| 宾川县| 昭平县| 行唐县| 垫江县| 泸州市| 晋宁县| 元阳县| 大姚县| 清镇市| 会理县| 诸城市| 沙坪坝区| 白银市| 镇沅| 泽普县| 衡南县| 武夷山市| 象州县| 邹平县| 鹿泉市| 嵩明县| 诏安县| 莫力| 南溪县| 建瓯市| 泽库县| 大新县| 长乐市| 多伦县| 临沭县| 卓尼县| 武汉市| 永年县| 宁国市| 盐池县| 和龙市| 聂荣县| 广灵县| 长宁区| 淅川县|