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

淺析Go語言中的緩沖區(qū)及其在fmt包中的應用

 更新時間:2024年01月31日 11:00:16   作者:沙蒿同學  
這篇文章主要為大家詳細介紹了Go語言中的緩沖區(qū)及其在fmt包中的應用的相關知識,文中的示例代碼講解詳細,感興趣的小伙伴可以了解一下

傳統(tǒng)的IO流程

在傳統(tǒng)的IO流程中,通常涉及以下幾個步驟:

  • 打開文件或建立網(wǎng)絡連接:首先,需要打開文件或建立網(wǎng)絡連接,以便進行讀取或寫入操作。這通常涉及到操作系統(tǒng)提供的系統(tǒng)調用,如open、socket等。
  • 讀取或寫入數(shù)據(jù):一旦文件或網(wǎng)絡連接打開,就可以進行數(shù)據(jù)的讀取或寫入操作。讀取操作將從文件或網(wǎng)絡連接中獲取數(shù)據(jù),而寫入操作將將數(shù)據(jù)寫入文件或發(fā)送到網(wǎng)絡連接中。這些操作通常涉及到系統(tǒng)調用,如readwrite。
  • 緩沖區(qū):為了提高IO性能,通常會使用緩沖區(qū)。緩沖區(qū)是一塊內存區(qū)域,用于臨時存儲要讀取或寫入的數(shù)據(jù)。數(shù)據(jù)首先被讀取到緩沖區(qū)中,然后從緩沖區(qū)中寫入到文件或網(wǎng)絡連接中,或者從緩沖區(qū)中讀取數(shù)據(jù)。
  • 關閉文件或網(wǎng)絡連接:當讀取或寫入操作完成后,需要關閉文件或網(wǎng)絡連接。這通常涉及到系統(tǒng)調用,如close

在傳統(tǒng)的IO流程中,每次讀取或寫入操作都會涉及到系統(tǒng)調用,這會導致較高的開銷。為了提高性能,通常會使用緩沖區(qū)來減少系統(tǒng)調用的次數(shù)。緩沖區(qū)可以一次讀取或寫入多個數(shù)據(jù),從而減少了系統(tǒng)調用的開銷。

緩沖區(qū)

上面我們了解到緩沖區(qū)這個概念,那什么是緩沖區(qū)呢?

內存緩沖區(qū)是計算機中的一種臨時存儲區(qū)域,用于暫時存儲數(shù)據(jù)。它通常用于提高數(shù)據(jù)讀寫的效率,減少對底層存儲設備的頻繁訪問。

緩沖區(qū)的主要目的是在數(shù)據(jù)的生產者和消費者之間起到一個中間層的作用。當數(shù)據(jù)被生產者生成時,它首先被寫入緩沖區(qū),而不是直接寫入到目標存儲設備。然后,消費者可以從緩沖區(qū)中讀取數(shù)據(jù)。

緩沖區(qū)的大小是有限的,一旦緩沖區(qū)被填滿,生產者必須等待消費者讀取數(shù)據(jù),以便為新的數(shù)據(jù)騰出空間。同樣,如果緩沖區(qū)為空,消費者必須等待生產者生成新的數(shù)據(jù)。

內存緩沖區(qū)可以用于各種場景,比如:

  • 文件讀寫:在讀取或寫入大文件時,可以使用內存緩沖區(qū)來提高讀寫性能。數(shù)據(jù)首先被讀取到緩沖區(qū)中,然后批量地寫入或讀取到磁盤上的文件。
  • 網(wǎng)絡通信:在網(wǎng)絡通信中,數(shù)據(jù)通常需要經(jīng)過網(wǎng)絡協(xié)議的封裝和解析。使用內存緩沖區(qū)可以將數(shù)據(jù)暫時存儲起來,以便進行協(xié)議處理和網(wǎng)絡傳輸。
  • 數(shù)據(jù)庫操作:在數(shù)據(jù)庫操作中,使用內存緩沖區(qū)可以提高數(shù)據(jù)的讀寫性能。數(shù)據(jù)首先被寫入緩沖區(qū),然后批量地寫入到數(shù)據(jù)庫中,或者從緩沖區(qū)中讀取數(shù)據(jù)進行查詢。

需要注意的是,內存緩沖區(qū)只是一個臨時存儲區(qū)域,數(shù)據(jù)在緩沖區(qū)中并不是持久化的。一旦程序結束或緩沖區(qū)被清空,緩沖區(qū)中的數(shù)據(jù)就會丟失。因此,在使用內存緩沖區(qū)時需要確保數(shù)據(jù)的正確性和一致性。

go緩沖區(qū)

在Go語言中,緩沖區(qū)的大小是由創(chuàng)建緩沖區(qū)時指定的參數(shù)決定的。在標準庫中,可以使用bufio包提供的NewWriterSize函數(shù)創(chuàng)建一個指定大小的緩沖區(qū)。

默認情況下,bufio.Writer的緩沖區(qū)大小為4096字節(jié)(4KB),即調用bufio.NewWriter創(chuàng)建的緩沖區(qū)大小為4096字節(jié)。這是因為4096字節(jié)是一個常見的磁盤塊大小,對于大多數(shù)應用場景來說,這個大小已經(jīng)足夠了。

如果需要自定義緩沖區(qū)的大小,可以使用bufio.NewWriterSize函數(shù)來指定緩沖區(qū)的大小。例如,可以通過bufio.NewWriterSize(writer, 8192)來創(chuàng)建一個大小為8192字節(jié)(8KB)的緩沖區(qū)。

為什么

為什么go編程中要設置緩沖區(qū)呢?其實我們上面都有提到:設置緩沖區(qū)的一個主要目的就是為了減少頻繁的IO操作。

在進行IO操作時,例如讀取或寫入文件,每次都直接操作底層的存儲設備(如磁盤或網(wǎng)絡)可能會導致性能下降。這是因為每次IO操作都需要進行系統(tǒng)調用,這涉及到內核和用戶空間之間的上下文切換,以及硬件設備的訪問延遲。

通過使用緩沖區(qū),可以將數(shù)據(jù)暫時存儲在內存中,而不是直接與底層存儲設備進行交互。這樣可以將多個小的IO操作合并為一個大的IO操作,從而減少了系統(tǒng)調用的次數(shù)。這種批量處理的方式通常比頻繁的小IO操作更高效。

此外,緩沖區(qū)還可以提供更好的數(shù)據(jù)傳輸效率。當數(shù)據(jù)被寫入緩沖區(qū)時,實際的IO操作可以被推遲到緩沖區(qū)被填滿或手動刷新緩沖區(qū)時才執(zhí)行。這樣可以減少IO操作的次數(shù),提高數(shù)據(jù)傳輸?shù)男省?/p>

go 緩沖區(qū)(Buffer)是分配在堆還是棧?

在Go語言中,緩沖區(qū)(Buffer)的申請是在堆上進行的。

Go語言中的??臻g是有限的,而且棧上的內存分配和釋放是由編譯器自動管理的,無法手動控制。因此,較大的緩沖區(qū)無法放在棧上進行申請。

相反,Go語言中的堆空間是用于動態(tài)分配內存的,可以手動控制內存的申請和釋放。當我們使用make關鍵字創(chuàng)建一個切片或映射時,內存就會在堆上進行動態(tài)分配。而bufio包中的緩沖區(qū)也是通過make函數(shù)在堆上進行申請的。

緩沖區(qū)的申請通常是在創(chuàng)建緩沖區(qū)時進行的,例如使用bufio.NewWriterbufio.NewWriterSize函數(shù)來創(chuàng)建一個緩沖區(qū)對象。這個過程會調用make函數(shù)來分配足夠大小的內存,并返回一個指向該內存的指針。

fmt打印

示例

fmt.Println("Hello, world!"),大家平時用得最多了,這不就是打印輸出到控制臺嘛

當執(zhí)行fmt.Println("Hello, world!")命令時,會調用fmt包內的Println函數(shù)來打印輸出。

首先,Println函數(shù)會根據(jù)傳入的參數(shù)列表構建一個字符串,并將其傳遞給Fprintln函數(shù)。Fprintln函數(shù)是fmt包內部的一個輔助函數(shù),它會將構建的字符串寫入到標準輸出(即控制臺)。

Fprintln函數(shù)內部,它會調用newPrinter函數(shù)來創(chuàng)建一個pp(printer)對象。pp對象是printer結構體的實例,它包含了打印輸出的相關配置和狀態(tài)信息。

接下來,Fprintln函數(shù)會調用pp.print方法來實際執(zhí)行打印輸出的操作。在print方法中,它會根據(jù)配置的格式化選項,將構建的字符串寫入到pp.buf緩沖區(qū)中。

如果緩沖區(qū)已滿,或者遇到換行符(\n),print方法會調用pp.write方法將緩沖區(qū)的內容寫入到標準輸出。write方法會使用os.Stdout作為目標,將緩沖區(qū)的內容寫入到控制臺。

最后,Fprintln函數(shù)會調用pp.free方法來釋放pp對象占用的內存,以及清空緩沖區(qū)。

總結起來,當執(zhí)行fmt.Println("Hello, world!")命令時,fmt包內部會構建打印輸出的字符串,并將其寫入到標準輸出。這個過程涉及到字符串的構建、緩沖區(qū)的管理和標準輸出的寫入。通過使用printer結構體和相關方法,fmt包實現(xiàn)了方便的打印輸出功能。

源碼查看

// ...
func main() {
    fmt.Println("Hello, world!")
}

// fmt 包
// ...
func Println(a ...any) (n int, err error) {
	return Fprintln(os.Stdout, a...)
}
// ...
func Fprintln(w io.Writer, a ...any) (n int, err error) {
	p := newPrinter()
	p.doPrintln(a)
	n, err = w.Write(p.buf)
	p.free()
	return
}

當打印內容很大怎么辦

當打印的內容超出了緩沖區(qū)的大小時,fmt包會動態(tài)擴展緩沖區(qū)的大小,以容納更大的數(shù)據(jù),并完整地輸出到標準輸出。

在執(zhí)行打印操作時,fmt包會檢查緩沖區(qū)的剩余空間是否足夠容納當前要打印的內容。如果空間不足,fmt包會自動擴展緩沖區(qū)的大小,通常是將緩沖區(qū)的大小翻倍。

例如,在默認情況下,fmt包的緩沖區(qū)大小為4KB。如果要打印的內容超過了4KB,fmt包會自動將緩沖區(qū)擴展到8KB,以容納更多的數(shù)據(jù)。如果仍然不夠,會繼續(xù)擴展到16KB,以此類推,直到能夠容納所有的數(shù)據(jù)。

當緩沖區(qū)大小足夠容納要打印的內容時,fmt包會將數(shù)據(jù)寫入緩沖區(qū)中。當緩沖區(qū)滿了或者遇到換行符(\n)時,fmt包會將緩沖區(qū)的內容寫入到標準輸出,確保完整地輸出所有的數(shù)據(jù)。

也就是說我有一個8k的打印內容,而緩沖區(qū)大小為4KB,那么在第一次寫入緩沖區(qū)后,緩沖區(qū)將被填滿。此時,fmt包會進行一次IO操作,將緩沖區(qū)的內容寫入標準輸出。

由于緩沖區(qū)已滿,第二次寫入操作將觸發(fā)另一次IO操作,將剩余的內容寫入標準輸出。

因此,在這種情況下,fmt包會進行兩次IO操作,將完整的8KB內容寫入標準輸出。第一次是在緩沖區(qū)填滿后,第二次是在第二次寫入時。

到此這篇關于淺析Go語言中的緩沖區(qū)及其在fmt包中的應用的文章就介紹到這了,更多相關Go緩沖區(qū)內容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • 一文帶你掌握Go語言并發(fā)模式中的Context的上下文管理

    一文帶你掌握Go語言并發(fā)模式中的Context的上下文管理

    在?Go?的日常開發(fā)中,Context?上下文對象無處不在,無論是處理網(wǎng)絡請求、數(shù)據(jù)庫操作還是調用?RPC?等場景,那你真的熟悉它的正確用法嗎,隨著本文一探究竟吧
    2023-05-05
  • golang sql連接池的實現(xiàn)方法詳解

    golang sql連接池的實現(xiàn)方法詳解

    database/sql是golang的標準庫之一,它提供了一系列接口方法,用于訪問關系數(shù)據(jù)庫。下面這篇文章主要給大家介紹了關于golang sql連接池用法的相關資料,文中通過示例代碼介紹的非常詳細,需要的朋友可以參考借鑒,下面來一起看看吧
    2018-09-09
  • golang 流式讀取和發(fā)送使用場景示例

    golang 流式讀取和發(fā)送使用場景示例

    這篇文章主要為大家介紹了golang 流式讀取和發(fā)送使用場景示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2023-12-12
  • golang 如何替換掉字符串里面的換行符\n

    golang 如何替換掉字符串里面的換行符\n

    這篇文章主要介紹了golang 替換掉字符串里面的換行符\n操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2021-03-03
  • Golang微服務框架Kratos實現(xiàn)Kafka消息隊列的方法

    Golang微服務框架Kratos實現(xiàn)Kafka消息隊列的方法

    消息隊列是大型分布式系統(tǒng)不可缺少的中間件,也是高并發(fā)系統(tǒng)的基石中間件,所以掌握好消息隊列MQ就變得極其重要,在本文當中,您將了解到:什么是消息隊列?什么是Kafka?怎樣在微服務框架Kratos當中應用Kafka進行業(yè)務開發(fā),需要的朋友可以參考下
    2023-09-09
  • go build和go install的區(qū)別介紹

    go build和go install的區(qū)別介紹

    這篇文章主要介紹了go build和go install的區(qū)別介紹,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧
    2020-12-12
  • Go+Redis緩存設計與優(yōu)化實現(xiàn)

    Go+Redis緩存設計與優(yōu)化實現(xiàn)

    本文主要介紹了Go+Redis緩存設計與優(yōu)化實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2025-02-02
  • Go語言進行多時區(qū)時間轉換的示例代碼

    Go語言進行多時區(qū)時間轉換的示例代碼

    本文介紹了使用Go語言進行多時區(qū)時間轉換,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2024-12-12
  • golang根據(jù)生日計算星座和屬相實例

    golang根據(jù)生日計算星座和屬相實例

    這篇文章主要為大家介紹了golang根據(jù)生日計算星座和屬相的示例代碼,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪
    2022-07-07
  • Golang如何編寫內存高效及CPU調優(yōu)的Go結構體

    Golang如何編寫內存高效及CPU調優(yōu)的Go結構體

    這篇文章主要介紹了Golang如何編寫內存高效及CPU調優(yōu)的Go結構體,結構體是包含多個字段的集合類型,用于將數(shù)據(jù)組合為記錄
    2022-07-07

最新評論