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

深入解析golang?bufio

 更新時(shí)間:2022年04月21日 10:34:33   作者:charlieroro  
這篇文章主要介紹了golang?bufio解析,golang的bufio庫使用緩存來一次性進(jìn)行大塊數(shù)據(jù)的讀寫,以此降低IO系統(tǒng)調(diào)用,提升性能,需要的朋友可以參考下

bufio 包介紹 

bufio包實(shí)現(xiàn)了有緩沖的I/O。它包裝一個(gè)io.Reader或io.Writer接口對(duì)象,創(chuàng)建另一個(gè)也實(shí)現(xiàn)了該接口,且同時(shí)還提供了緩沖和一些文本I/O的幫助函數(shù)的對(duì)象。

golang bufio

當(dāng)頻繁地對(duì)少量數(shù)據(jù)讀寫時(shí)會(huì)占用IO,造成性能問題。golang的bufio庫使用緩存來一次性進(jìn)行大塊數(shù)據(jù)的讀寫,以此降低IO系統(tǒng)調(diào)用,提升性能。

在Transport中可以設(shè)置一個(gè)名為WriteBufferSize的參數(shù),該參數(shù)指定了底層(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進(jìn)行寫

可以使用bufio.NewWriter初始化一個(gè)大小為4096字節(jié)的Writer(見下),或使用bufio.NewWriterSize初始化一個(gè)指定大小的Writer。

Writer中的主要參數(shù)為緩存區(qū)buf,緩存區(qū)中的數(shù)據(jù)偏移量n以及寫入接口wr

type Writer struct {
	err error
	buf []byte
	n   int
	wr  io.Writer
}

bufio.Writer方法可以一次性寫入緩存中的數(shù)據(jù),通常有如下三種情況:

  • 緩存中滿數(shù)據(jù)
  • 緩存中仍有空間
  • 待寫入的數(shù)據(jù)大于緩存的大小

緩存中滿數(shù)據(jù)

當(dāng)緩存中滿數(shù)據(jù)時(shí),會(huì)執(zhí)行寫操作。

緩存中仍有空間

如果緩存中仍有數(shù)據(jù),則不會(huì)執(zhí)行寫入動(dòng)作,除非調(diào)用Flush()方法。

待寫入的數(shù)據(jù)大于緩存的大小

由于此時(shí)緩存無法緩存足夠的數(shù)據(jù),此時(shí)會(huì)跳過緩存直接執(zhí)行寫操作

type Writer int
func (*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 full
	bw1.Write([]byte{'1'})
	bw1.Write([]byte{'2'})
	bw1.Write([]byte{'3'})
	bw1.Write([]byte{'4'}) // write - buffer is full
	// Case 2: Buffer has space
    bw1.Write([]byte{'5'}) //此時(shí)buffer中無法容納更多的數(shù)據(jù),執(zhí)行寫操作,寫入 []byte{'1','2','3','4'}
	err = bw1.Flush() // forcefully write remaining
	if err != nil {
		panic(err)
	}
	// Case 3: (too) large write for buffer
	// Will skip buffer and write directly
	bw1.Write([]byte("12345")) //buffer不足,直接執(zhí)行寫操作
//結(jié)果:
Writing: 1234
Writing: 5
Writing: 12345

緩存重用

申請(qǐng)緩存對(duì)性能是有損耗的,可以使用Reset方法重置緩存,其內(nèi)部只是將Writer的數(shù)據(jù)偏移量n置0。

wr := new(Writer)
bw := bufio.NewWriterSize(wr,2) 
bw.Reset(wr) 

獲取緩存的可用空間數(shù)

Available()方法可以返回緩存的可用空間數(shù),即len(Writer.buf)-Writer.n

使用bufio進(jìn)行讀

與用于寫數(shù)據(jù)的Writer類似,讀數(shù)據(jù)也有一個(gè)Reader,可以使用NewReader初始化一個(gè)大小為4096字節(jié)的Reader,或使用NewReaderSize初始化一個(gè)指定大小的Reader(要求最小為16字節(jié))。Reader也有一個(gè)記錄偏移量的變量r

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 // last byte read for UnreadByte; -1 means invalid
	lastRuneSize int // size of last rune read for UnreadRune; -1 means invalid
}

Peek

該方法會(huì)返回buf中的前n個(gè)字節(jié)的內(nèi)容,但與Read操作不同的是,它不會(huì)消費(fèi)緩存中的數(shù)據(jù),即不會(huì)增加數(shù)據(jù)偏移量,因此通常也會(huì)用于判斷是否讀取結(jié)束(EOF)。通常有如下幾種情況:

  • 如果peak的值小于緩存大小,則返回相應(yīng)的內(nèi)容
  • 如果peak的值大于緩存大小,則返回bufio.ErrBufferFull錯(cuò)誤
  • 如果peak的值包含EOF且小于緩存大小,則返回EOF

Read

將數(shù)據(jù)讀取到p,涉及將數(shù)據(jù)從緩存拷貝到p。

func (b *Reader) Read(p []byte) (n int, err error)

ReadSlice

該方法會(huì)讀從緩存讀取數(shù)據(jù),直到遇到第一個(gè)delim。如果緩存中沒有delim,則返回EOF,如果查詢的長度超過了緩存大小,則返回 io.ErrBufferFull 錯(cuò)誤。

func (b *Reader) ReadSlice(delim byte) (line []byte, err error) 

例如delim',',則下面會(huì)返回的內(nèi)容為1234,。

r := strings.NewReader("1234,567")
rb := bufio.NewReaderSize(r, 20)
fmt.Println(rb.ReadSlice(','))
// 結(jié)果:[49 50 51 52 44] <nil>

注意:ReadSlice返回的是原始緩存中的內(nèi)容,如果針對(duì)緩存作并發(fā)操作,則返回的內(nèi)容有可能被其他操作覆蓋。因此在官方注釋里面有寫,建議使用ReadBytesReadString。但ReadBytesReadString涉及內(nèi)存申請(qǐng)和拷貝,因此會(huì)影響性能。在追求高性能的場(chǎng)景下,建議外部使用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,但在返回時(shí)會(huì)移除\n 或\r\n。需要注意的是,如果切片中沒有找到換行符,則不會(huì)返回EOF或io.ErrBufferFull 錯(cuò)誤,相反,它會(huì)將isPrefix置為true

ReadBytes

ReadSlice類似,但它會(huì)返回一個(gè)新的切片,因此便于并發(fā)使用。如果找不到delim,ReadBytes會(huì)返回io.EOF

func (b *Reader) ReadBytes(delim byte) ([]byte, error)

Scanner

scanner可以不斷將數(shù)據(jù)讀取到緩存(默認(rèn)64*1024字節(jié))。

    rb := strings.NewReader("12345678901234567890")
	scanner := bufio.NewScanner(rb)
	for scanner.Scan() {
		fmt.Printf("Token (Scanner): %q\n", scanner.Text())
	}
	// 結(jié)果:Token (Scanner): "12345678901234567890"

參考

how-to-read-and-write-with-golang-bufio

到此這篇關(guān)于golang bufio解析的文章就介紹到這了,更多相關(guān)golang bufio內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 解決go mod私有倉庫拉取的問題

    解決go mod私有倉庫拉取的問題

    這篇文章主要介紹了解決go mod私有倉庫拉取的問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2021-05-05
  • 1行Go代碼實(shí)現(xiàn)反向代理的示例

    1行Go代碼實(shí)現(xiàn)反向代理的示例

    這篇文章主要介紹了1行Go代碼實(shí)現(xiàn)反向代理的示例,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來看看吧
    2018-08-08
  • 深入理解Go語言中的結(jié)構(gòu)體

    深入理解Go語言中的結(jié)構(gòu)體

    本文主要介紹了深入理解Go語言中的結(jié)構(gòu)體,包括定義結(jié)構(gòu)體、聲明結(jié)構(gòu)體變量、使用結(jié)構(gòu)體、結(jié)構(gòu)體關(guān)聯(lián)函數(shù)、new、組合等,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-11-11
  • 如何使用?Go?獲取你的?IP?地址(推薦)

    如何使用?Go?獲取你的?IP?地址(推薦)

    在Go語言中,獲取IP地址分為公共IP和私有IP兩種方式,公共IP地址通過外部API獲取,本文給大家介紹如何使用?Go?獲取你的?IP?地址,感興趣的朋友跟隨小編一起看看吧
    2024-09-09
  • Go語言中reflect.DeepEqual函數(shù)的具體使用

    Go語言中reflect.DeepEqual函數(shù)的具體使用

    本文主要介紹了Go語言中reflect.DeepEqual函數(shù)的具體使用,reflect.DeepEqual()函數(shù)是用來比較兩個(gè)值是否相等的方法,下面就來介紹一下,感興趣的可以了解一下
    2024-08-08
  • Go依賴注入工具wire的具體使用

    Go依賴注入工具wire的具體使用

    本文主要介紹了Go依賴注入工具wire的具體使用,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-05-05
  • golang如何去除 context 的 deadline

    golang如何去除 context 的 deadline

    在使用 context 的時(shí)候遇到了開協(xié)程處理任務(wù)的情況,但是直接在協(xié)程里使用主線程的 context 會(huì)導(dǎo)致當(dāng)主線程返回時(shí)協(xié)程任務(wù)也會(huì)因?yàn)?nbsp;context cancel 而失敗,本文提供了兩種辦法可以取消掉 context 里的 timeout 和 deadline,再設(shè)置一個(gè)新的 timeout 上去
    2023-03-03
  • Go 如何使用原始套接字捕獲網(wǎng)卡流量

    Go 如何使用原始套接字捕獲網(wǎng)卡流量

    為了減少對(duì)環(huán)境的依賴可以使用原始套接字捕獲網(wǎng)卡流量,然后使用?gopacket?的協(xié)議解析功能,這樣就省去了解析這部分的工作量,正確性也可以得到保證,同時(shí) CGO 也可以關(guān)閉,這篇文章主要介紹了Go 使用原始套接字捕獲網(wǎng)卡流量,需要的朋友可以參考下
    2024-07-07
  • Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說明

    Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說明

    這篇文章主要介紹了Golang中基礎(chǔ)的命令行模塊urfave/cli的用法說明,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • golang中的nil接收器詳解

    golang中的nil接收器詳解

    這篇文章主要介紹了golang中的nil接收器,本文通過實(shí)例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-10-10

最新評(píng)論

澎湖县| 安远县| 台山市| 尼木县| 栖霞市| 吉林市| 乐山市| 原阳县| 建宁县| 新巴尔虎右旗| 遵义市| 商城县| 扎囊县| 平昌县| 龙口市| 博爱县| 繁昌县| 闽侯县| 澄迈县| 酉阳| 建昌县| 上饶县| 镇赉县| 柳河县| 凤翔县| 余江县| 商洛市| 泰兴市| 西城区| 兴业县| 淳化县| 崇义县| 班戈县| 双牌县| 大名县| 安阳市| 阳高县| 镇坪县| 突泉县| 玉溪市| 长寿区|