欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

GoLang bytes.Buffer基礎(chǔ)使用方法詳解

 更新時(shí)間:2023年03月17日 09:43:39   作者:鯤鵬飛九萬(wàn)里  
Go標(biāo)準(zhǔn)庫(kù)中的bytes.Buffer(下文用Buffer表示)類(lèi)似于一個(gè)FIFO的隊(duì)列,它是一個(gè)流式字節(jié)緩沖區(qū),我們可以持續(xù)向Buffer尾部寫(xiě)入數(shù)據(jù),從Buffer頭部讀取數(shù)據(jù)。當(dāng)Buffer內(nèi)部空間不足以滿足寫(xiě)入數(shù)據(jù)的大小時(shí),會(huì)自動(dòng)擴(kuò)容

一、bytes.Buffer的基礎(chǔ)知識(shí)

strings.Builder一樣,bytes.Buffer也是開(kāi)箱即用的。

bytes.Buffer類(lèi)型的用途主要是作為字節(jié)序列的緩沖區(qū)。

在內(nèi)部,bytes.Buffer類(lèi)型使用字節(jié)切片作為內(nèi)容容器,并有一個(gè)int類(lèi)型的字段作為已讀計(jì)數(shù),這個(gè)已讀計(jì)數(shù)無(wú)法通過(guò)bytes.Buffer提供的方法計(jì)算出來(lái)。

	var buffer1 bytes.Buffer
	contents := "Simple byte buffer for marshaling data"
  // Write contents "Simple byte buffer for marshaling data"
	fmt.Printf("Write contents %q\n", contents)
	buffer1.WriteString(contents)
  // The length of buffer: 38
	fmt.Printf("The length of buffer: %d\n", buffer1.Len())
  // The capacity of buffer: 64
	fmt.Printf("The capacity of buffer: %d\n", buffer1.Cap())

strings.Reader類(lèi)型的Len方法一樣,buffer1的Len方法返回的也是內(nèi)容容器中未被讀取部分的長(zhǎng)度,而不是其中已存內(nèi)容的總長(zhǎng)度。

Buffer 值的長(zhǎng)度是未讀內(nèi)容的長(zhǎng)度,而不是已讀內(nèi)容的長(zhǎng)度。

	p1 := make([]byte, 7)
	n, _ := buffer1.Read(p1)
	// 7 bytes were read. (call Read)
	fmt.Printf("%d bytes were read. (call Read)\n", n)
	// The length of buffer: 31
	fmt.Printf("The length of buffer: %d\n", buffer1.Len())
	// The capacity of buffer: 64
	fmt.Printf("The capacity of buffer: %d\n", buffer1.Cap())

Buffer值的容量是它的內(nèi)容容器(也就是那個(gè)字節(jié)切片)的容量,它只與當(dāng)前值之上的寫(xiě)操作有關(guān),并隨著內(nèi)容的寫(xiě)入而不斷增長(zhǎng)。

二、bytes.Buffer類(lèi)型的值已讀計(jì)數(shù)的作用

讀取內(nèi)容時(shí),相應(yīng)方法會(huì)依據(jù)已讀計(jì)數(shù)找到未讀內(nèi)容,并在讀取之后更新計(jì)數(shù);

相應(yīng)方法包括所有名稱以Read開(kāi)頭的方法,以及Next方法和WriteTo方法。

寫(xiě)入內(nèi)容時(shí),如需擴(kuò)容,相應(yīng)方法會(huì)根據(jù)已讀計(jì)數(shù)實(shí)現(xiàn)擴(kuò)容策略;

寫(xiě)入時(shí),如果沒(méi)有足夠的容量,就會(huì)對(duì)容器進(jìn)行擴(kuò)容。

擴(kuò)容時(shí),方法會(huì)在必要時(shí),依據(jù)已讀計(jì)數(shù)找到未讀部分,并把其中的內(nèi)容拷貝到擴(kuò)展容器的頭部位置。然后,方法會(huì)把已讀計(jì)數(shù)值置為0。

相應(yīng)方法包括所有名稱以Write開(kāi)頭的方法,以及ReadFrom方法。

截?cái)鄡?nèi)容時(shí),相應(yīng)方法截?cái)嗟臅r(shí)已讀計(jì)數(shù)代表索引之后的未讀部分;

截?cái)喾椒═runcate,接受一個(gè)int類(lèi)型的參數(shù),表示在截?cái)鄷r(shí)需要保留頭部多少個(gè)字節(jié)。

這里的頭部是未讀部分的頭部,而不是內(nèi)容容器的頭部。

這種情況下,已讀計(jì)數(shù)的值再加上參數(shù)值后得到的和,就是內(nèi)容容器新的總長(zhǎng)度。

讀回退時(shí),相應(yīng)方法會(huì)使用已讀計(jì)數(shù)記錄回退點(diǎn);

用于讀回退的方法有UnreadByte和UnreadRune。這兩個(gè)方法分別用于回退一個(gè)字節(jié)和回退一個(gè)Unicode字符。

回退的前提是,在調(diào)用它們之前的那一個(gè)操作必須是“讀取”,并且是成功的讀取,否則這些方法就只會(huì)忽略后續(xù)操作并返回一個(gè)非nil的錯(cuò)誤值。

只有緊挨在調(diào)用ReadRune方法之后,對(duì)UnreadRune方法對(duì)調(diào)用才能夠成功完成。

重置內(nèi)容時(shí),相應(yīng)方法會(huì)把已讀計(jì)數(shù)置為0;

導(dǎo)出內(nèi)容時(shí),相應(yīng)方法只會(huì)導(dǎo)出已讀計(jì)數(shù)代表的索引之后的未讀部分;

Buffer值的Bytes和String方法,只會(huì)訪問(wèn)未讀部分的內(nèi)容,并返回相應(yīng)的結(jié)果值。

獲取長(zhǎng)度時(shí),相應(yīng)方法會(huì)依據(jù)已讀計(jì)數(shù)和內(nèi)容容器的長(zhǎng)度,計(jì)算未讀部分的長(zhǎng)度并返回;

Buffer值的Len方法返回的是內(nèi)容容器未讀部分的長(zhǎng)度。

三、bytes.Buffer的擴(kuò)容策略

bytes.Buffer既可以手動(dòng)擴(kuò)容,也可以自動(dòng)擴(kuò)容。除非完全確定后續(xù)內(nèi)容所需的字節(jié)數(shù),否則讓Buffer自動(dòng)擴(kuò)容就好了。這兩種方式的擴(kuò)容策略一樣。

擴(kuò)容策略:

判斷內(nèi)容容器的剩余容量,是否滿足調(diào)用方的要求,是否足夠容納新的內(nèi)容;

如果剩余容量滿足容納新的內(nèi)容,就在當(dāng)前的內(nèi)容容器之上,進(jìn)行長(zhǎng)度擴(kuò)容;

buf = buf[:length+need]

如果剩余容量不滿足容納新的內(nèi)容,就會(huì)用新的內(nèi)容容器去替代原有的內(nèi)容容器,從而實(shí)現(xiàn)擴(kuò)容;

這里有一個(gè)優(yōu)化,如果當(dāng)前內(nèi)容容器的容量的一半,仍然大于或等于現(xiàn)有長(zhǎng)度(即未讀字節(jié)數(shù))再加上另需字節(jié)數(shù)的和,即:

cap(buf)/2 >= len(buf) + need

那么擴(kuò)容代碼就會(huì)復(fù)用現(xiàn)有的內(nèi)容容器,并把容器中的未讀內(nèi)容拷貝到它的頭部位置。

這意味著,其中的已讀內(nèi)容,將會(huì)全部被未讀內(nèi)容和之后的新內(nèi)容覆蓋掉。

如果當(dāng)前內(nèi)容容器的容量小于新長(zhǎng)度的二倍。這時(shí),就會(huì)把原有容器中的未讀內(nèi)容拷貝進(jìn)去,最后再用新的容器替換掉原有的容器。這個(gè)新容器將會(huì)等于原有容量的二倍,再加上另需字節(jié)數(shù)的和。

新容器的容量 = 原有容量 * 2 + 所需字節(jié)數(shù)

擴(kuò)容還會(huì)把已讀計(jì)數(shù)置為0。

對(duì)于處于零值狀態(tài)的Buffer值來(lái)說(shuō),如果第一次擴(kuò)容時(shí)另需的字節(jié)數(shù)小于等于64,那么該值就會(huì)基于一個(gè)預(yù)先定義好的、長(zhǎng)度為64的字節(jié)數(shù)組來(lái)創(chuàng)建內(nèi)容容器。

這種情況下,容器的容量就是64。這樣做的目的是為了讓Buffer值在剛被真正使用的時(shí)候,可以快速的做好準(zhǔn)備。

四、bytes.Buffer的哪些方法會(huì)造成內(nèi)容的泄露

這里的內(nèi)容泄露是指,使用Buffer值的一方通過(guò)某種非標(biāo)準(zhǔn)的方式,得到本不該得到的內(nèi)容。

bytes.Buffer中,Bytes方法和Next方法都有可能會(huì)造成內(nèi)容的泄露。原因在于,它們都把基于內(nèi)容容器的切片直接返回給了方法的調(diào)用方。

通過(guò)切片,我們可以直接訪問(wèn)和操縱它們的底層數(shù)組,不論這個(gè)切片是基于某個(gè)數(shù)組得來(lái)的,還是痛哦過(guò)對(duì)另一個(gè)切片做切片操作獲得的,都是如此。

bytes.Buffer的Bytes方法和Next方法返回的字節(jié)切片,都是通過(guò)對(duì)內(nèi)容容器的切片做切片操作得到的。

	contents := "ab"
	buffer1 := bytes.NewBufferString(contents)
	// The capacity of new buffer with contents "ab": 8
	// 容量為何為8,看 runtime/string.go#stringtoslicebyte()
	fmt.Printf("The capacity of new buffer with contents %q: %d\n", contents, buffer1.Cap())
	unreadBytes := buffer1.Bytes()
	// The unread bytes of the buffer: [97 98]
	fmt.Printf("The unread bytes of the buffer: %v\n", unreadBytes)
	buffer1.WriteString("cdefg")
	// The capacity of new buffer with contents "ab": 8
	fmt.Printf("The capacity of new buffer with contents %q: %d\n", contents, buffer1.Cap())
	unreadBytes = unreadBytes[:cap(unreadBytes)]
	// 基于前面的內(nèi)容獲取到結(jié)果值
	// The unread bytes of the buffer: [97 98 99 100 101 102 103 0]
	fmt.Printf("The unread bytes of the buffer: %v\n", unreadBytes)
	// 操縱buffer
	unreadBytes[len(unreadBytes)-2] = byte('X')
	// The unread bytes of the buffer: [97 98 99 100 101 102 88 0]
	fmt.Printf("The unread bytes of the buffer: %v\n", unreadBytes)

到此這篇關(guān)于GoLang bytes.Buffer基礎(chǔ)使用方法詳解的文章就介紹到這了,更多相關(guān)Go bytes.Buffer內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 一篇文章帶你輕松搞懂Golang的error處理

    一篇文章帶你輕松搞懂Golang的error處理

    在進(jìn)行后臺(tái)開(kāi)發(fā)的時(shí)候,錯(cuò)誤處理是每個(gè)程序員都會(huì)遇到的問(wèn)題,下面這篇文章主要給大家介紹了關(guān)于Golang中error處理的相關(guān)資料,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下
    2022-07-07
  • golang?struct?json?tag的使用以及深入講解

    golang?struct?json?tag的使用以及深入講解

    這篇文章主要給大家介紹了關(guān)于golang?struct?json?tag的使用以及深入講解,文中通過(guò)實(shí)例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下
    2022-02-02
  • Go語(yǔ)言從單體服務(wù)到微服務(wù)設(shè)計(jì)方案詳解

    Go語(yǔ)言從單體服務(wù)到微服務(wù)設(shè)計(jì)方案詳解

    這篇文章主要為大家介紹了Go語(yǔ)言從單體服務(wù)到微服務(wù)設(shè)計(jì)方案詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-03-03
  • Go數(shù)據(jù)庫(kù)遷移的實(shí)現(xiàn)步驟

    Go數(shù)據(jù)庫(kù)遷移的實(shí)現(xiàn)步驟

    本文主要介紹了Go數(shù)據(jù)庫(kù)遷移的實(shí)現(xiàn)步驟,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解

    golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本詳解

    這篇文章主要給大家介紹了關(guān)于golang如何實(shí)現(xiàn)mapreduce單進(jìn)程版本的相關(guān)資料,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01
  • 解決GOPATH在GOLAND中的坑

    解決GOPATH在GOLAND中的坑

    這篇文章主要介紹了解決GOPATH在GOLAND中的坑,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧
    2020-12-12
  • GO的range如何使用詳解

    GO的range如何使用詳解

    本文主要介紹了GO的range如何使用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-02-02
  • 如何使用Golang創(chuàng)建與讀取Excel文件

    如何使用Golang創(chuàng)建與讀取Excel文件

    我最近工作忙于作圖,圖表,需要自己準(zhǔn)備數(shù)據(jù)源,所以經(jīng)常和Excel打交道,下面這篇文章主要給大家介紹了關(guān)于如何使用Golang創(chuàng)建與讀取Excel文件的相關(guān)資料,需要的朋友可以參考下
    2022-07-07
  • 淺析Go語(yǔ)言如何避免數(shù)據(jù)競(jìng)爭(zhēng)Data?Race和競(jìng)態(tài)條件Race?Condition

    淺析Go語(yǔ)言如何避免數(shù)據(jù)競(jìng)爭(zhēng)Data?Race和競(jìng)態(tài)條件Race?Condition

    在并發(fā)編程中,數(shù)據(jù)競(jìng)爭(zhēng)?(Data?Race)?和?競(jìng)態(tài)條件?(Race?Condition)?是兩個(gè)常見(jiàn)的問(wèn)題,本文將簡(jiǎn)單介紹一下二者如何避免,有需要的可以了解下
    2025-01-01
  • golang中json反序列化可能遇到的問(wèn)題

    golang中json反序列化可能遇到的問(wèn)題

    這篇文章主要給大家介紹了關(guān)于golang中json反序列化可能遇到的問(wèn)題的解決方法,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。
    2018-01-01

最新評(píng)論