91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

GoLang?bytes.Buffer怎么使用

發布時間:2023-03-17 10:22:26 來源:億速云 閱讀:119 作者:iii 欄目:開發技術

這篇文章主要介紹“GoLang bytes.Buffer怎么使用”的相關知識,小編通過實際案例向大家展示操作過程,操作方法簡單快捷,實用性強,希望這篇“GoLang bytes.Buffer怎么使用”文章能幫助大家解決問題。

一、bytes.Buffer的基礎知識

strings.Builder一樣,bytes.Buffer也是開箱即用的。

bytes.Buffer類型的用途主要是作為字節序列的緩沖區。

在內部,bytes.Buffer類型使用字節切片作為內容容器,并有一個int類型的字段作為已讀計數,這個已讀計數無法通過bytes.Buffer提供的方法計算出來。

	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類型的Len方法一樣,buffer1的Len方法返回的也是內容容器中未被讀取部分的長度,而不是其中已存內容的總長度。

Buffer 值的長度是未讀內容的長度,而不是已讀內容的長度。

	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值的容量是它的內容容器(也就是那個字節切片)的容量,它只與當前值之上的寫操作有關,并隨著內容的寫入而不斷增長。

二、bytes.Buffer類型的值已讀計數的作用

讀取內容時,相應方法會依據已讀計數找到未讀內容,并在讀取之后更新計數;

相應方法包括所有名稱以Read開頭的方法,以及Next方法和WriteTo方法。

寫入內容時,如需擴容,相應方法會根據已讀計數實現擴容策略;

寫入時,如果沒有足夠的容量,就會對容器進行擴容。

擴容時,方法會在必要時,依據已讀計數找到未讀部分,并把其中的內容拷貝到擴展容器的頭部位置。然后,方法會把已讀計數值置為0。

相應方法包括所有名稱以Write開頭的方法,以及ReadFrom方法。

截斷內容時,相應方法截斷的時已讀計數代表索引之后的未讀部分;

截斷方法Truncate,接受一個int類型的參數,表示在截斷時需要保留頭部多少個字節。

這里的頭部是未讀部分的頭部,而不是內容容器的頭部。

這種情況下,已讀計數的值再加上參數值后得到的和,就是內容容器新的總長度。

讀回退時,相應方法會使用已讀計數記錄回退點;

用于讀回退的方法有UnreadByte和UnreadRune。這兩個方法分別用于回退一個字節和回退一個Unicode字符。

回退的前提是,在調用它們之前的那一個操作必須是“讀取”,并且是成功的讀取,否則這些方法就只會忽略后續操作并返回一個非nil的錯誤值。

只有緊挨在調用ReadRune方法之后,對UnreadRune方法對調用才能夠成功完成。

重置內容時,相應方法會把已讀計數置為0;

導出內容時,相應方法只會導出已讀計數代表的索引之后的未讀部分;

Buffer值的Bytes和String方法,只會訪問未讀部分的內容,并返回相應的結果值。

獲取長度時,相應方法會依據已讀計數和內容容器的長度,計算未讀部分的長度并返回;

Buffer值的Len方法返回的是內容容器未讀部分的長度。

三、bytes.Buffer的擴容策略

bytes.Buffer既可以手動擴容,也可以自動擴容。除非完全確定后續內容所需的字節數,否則讓Buffer自動擴容就好了。這兩種方式的擴容策略一樣。

擴容策略:

判斷內容容器的剩余容量,是否滿足調用方的要求,是否足夠容納新的內容;

如果剩余容量滿足容納新的內容,就在當前的內容容器之上,進行長度擴容;

buf = buf[:length+need]

如果剩余容量不滿足容納新的內容,就會用新的內容容器去替代原有的內容容器,從而實現擴容;

這里有一個優化,如果當前內容容器的容量的一半,仍然大于或等于現有長度(即未讀字節數)再加上另需字節數的和,即:

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

那么擴容代碼就會復用現有的內容容器,并把容器中的未讀內容拷貝到它的頭部位置。

這意味著,其中的已讀內容,將會全部被未讀內容和之后的新內容覆蓋掉。

如果當前內容容器的容量小于新長度的二倍。這時,就會把原有容器中的未讀內容拷貝進去,最后再用新的容器替換掉原有的容器。這個新容器將會等于原有容量的二倍,再加上另需字節數的和。

新容器的容量 = 原有容量 * 2 + 所需字節數

擴容還會把已讀計數置為0。

對于處于零值狀態的Buffer值來說,如果第一次擴容時另需的字節數小于等于64,那么該值就會基于一個預先定義好的、長度為64的字節數組來創建內容容器。

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

四、bytes.Buffer的哪些方法會造成內容的泄露

這里的內容泄露是指,使用Buffer值的一方通過某種非標準的方式,得到本不該得到的內容。

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

通過切片,我們可以直接訪問和操縱它們的底層數組,不論這個切片是基于某個數組得來的,還是痛哦過對另一個切片做切片操作獲得的,都是如此。

bytes.Buffer的Bytes方法和Next方法返回的字節切片,都是通過對內容容器的切片做切片操作得到的。

	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)]
	// 基于前面的內容獲取到結果值
	// 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)

關于“GoLang bytes.Buffer怎么使用”的內容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業相關的知識,可以關注億速云行業資訊頻道,小編每天都會為大家更新不同的知識點。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

平阴县| 前郭尔| 平阳县| 留坝县| 宁夏| 旬邑县| 泰来县| 和龙市| 沂源县| 新平| 双流县| 蛟河市| 嘉黎县| 南丰县| 松潘县| 杭锦后旗| 璧山县| 和硕县| 鄂伦春自治旗| 格尔木市| 托克托县| 石首市| 老河口市| 永昌县| 阿合奇县| 渭源县| 巫山县| 衡山县| 江西省| 常熟市| 交城县| 江川县| 济源市| 安达市| 太白县| 民权县| 克什克腾旗| 时尚| 灵武市| 利津县| 阿克苏市|