精品专区-精品自拍9-精品自拍三级乱伦-精品自拍视频-精品自拍视频曝光-精品自拍小视频

網站建設資訊

NEWS

網站建設資訊

go語言buffer go語言適合做什么

golang中bufio包

一、介紹go標準庫中的bufio

創新互聯公司專注于水富網站建設服務及定制,我們擁有豐富的企業做網站經驗。 熱誠為您提供水富營銷型網站建設,水富網站制作、水富網頁設計、水富網站官網定制、小程序開發服務,打造水富網絡公司原創品牌,更為您提供水富網站排名全網營銷落地服務。

最近用golang寫了一個處理文件的腳本,由于其中涉及到了文件讀寫,開始使用golang中的 io 包,后來發現golang 中提供了一個bufio的包,使用這個包可以大幅提高文件讀寫的效率,于是在網上搜索同樣的文件讀寫為什么bufio 要比io 的讀寫更快速呢?根據網上的資料和閱讀源碼,以下來詳細解釋下bufio的高效如何實現的。

bufio 包介紹

bufio包實現了有緩沖的I/O。它包裝一個io.Reader或io.Writer接口對象,創建另一個也實現了該接口,且同時還提供了緩沖和一些文本I/O的幫助函數的對象。

以上為官方包的介紹,在其中我們能了解到的信息如下:

bufio 是通過緩沖來提高效率

簡單的說就是,把文件讀取進緩沖(內存)之后再讀取的時候就可以避免文件系統的io 從而提高速度。同理,在進行寫操作時,先把文件寫入緩沖(內存),然后由緩沖寫入文件系統。看完以上解釋有人可能會表示困惑了,直接把 內容-文件 和 內容-緩沖-文件相比, 緩沖區好像沒有起到作用嘛。其實緩沖區的設計是為了存儲多次的寫入,最后一口氣把緩沖區內容寫入文件。下面會詳細解釋

bufio 封裝了io.Reader或io.Writer接口對象,并創建另一個也實現了該接口的對象

io.Reader或io.Writer 接口實現read() 和 write() 方法,對于實現這個接口的對象都是可以使用這兩個方法的

注明:介紹內容來自博主 LiangWenT

,原文鏈接: ,在查找資料時,發現這篇博客的內容很好理解

bufio包實現了緩存IO。它包裝了io.Reader和io.Write對象,創建了另外的Reader和Writer對象,它們也實現了io.Reader和io.Write接口,具有緩存。注意:緩存是放在主存中,既然是保存在主存里,斷電會丟失數據,那么要及時保存數據。

二、常用內容

1、Reader類型

NewReaderSize

作用:NewReaderSize將rd封裝成一個帶緩存的bufio.Reader對象。緩存大小由size指定(如果小于16則會被設為16)。如果rd的基類型就是有足夠緩存的bufio.Reader類型,則直接將rd轉換為基類型返回。

NewReader

funcReader相當于NewReaderSize(rd, 4096)

Peek

Peek返回緩存的一個切片,該切片引用緩存中前n個字節的數據,該操作不會將數據讀出,只是引用,引用的數據在下一次讀取操作之前有效的。如果切片長度小于n,則返回一個錯誤信息說明原因。如果n大于緩存的總大小,則返回ErrBufferFull。

Read

Read從b中數據到p中,返回讀出的字節數和遇到的錯誤。如果緩存不為空,則只能讀出緩沖中的數據,不會從底層io.Reader中提取數據,如果緩存為空,則:

1、len(p) = 緩存大小,則跳過緩存,直接從底層io.Reader中讀出到p中

2、len(p) 緩存大小,則先將數據從底層io.Reader中讀取到緩存中,再從緩存讀取到p中。

Buffered

Buffered返回緩存中未讀取的數據的長度。

Discard

Discard跳過后續的n個字節的數據,返回跳過的字節數。

Writer類型和方法

write結構

NewWriteSize

NewWriterSize將wr封裝成一個帶緩存的bufio.Writer對象,緩存大小由size指定(如果小于4096則會被設置未4096)。

NewWrite

NewWriter相等于NewWriterSize(wr, 4096)

WriteString

WriteString功能同Write,只不過寫入的是字符串

WriteRune

WriteRune向b寫入r的UTF-8編碼,返回r的編碼長度。

Flush

Available

Available 返回緩存中未使用的空間的長度

Buffered

Buffered返回緩存中未提交的數據長度

Reset

Reset將b的底層Write重新指定為w,同時丟棄緩存中的所有數據,復位所有標記和錯誤信息。相當于創建了一個新的bufio.Writer。

GO中還提供了Scanner類型,處理一些比較簡單的場景。如處理按行讀取輸入序列或空格分隔的詞等。

內容來自:

參考鏈接:

1)

2)

go語言string之Buffer與Builder

操作字符串離不開字符串的拼接,但是Go中string是只讀類型,大量字符串的拼接會造成性能問題。

拼接字符串,無外乎四種方式,采用“+”,“fmt.Sprintf()”,"bytes.Buffer","strings.Builder"

上面我們創建10萬字符串拼接的測試,可以發現"bytes.Buffer","strings.Builder"的性能最好,約是“+”的1000倍級別。

這是由于string是不可修改的,所以在使用“+”進行拼接字符串,每次都會產生申請空間,拼接,復制等操作,數據量大的情況下非常消耗資源和性能。而采用Buffer等方式,都是預先計算拼接字符串數組的總長度(如果可以知道長度),申請空間,底層是slice數組,可以以append的形式向后進行追加。最后在轉換為字符串。這申請了不斷申請空間的操作,也減少了空間的使用和拷貝的次數,自然性能也高不少。

bytes.buffer是一個緩沖byte類型的緩沖器存放著都是byte

是一個變長的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一個 空的 buffer,但是可以使用,底層就是一個 []byte, 字節切片。

向Buffer中寫數據,可以看出Buffer中有個Grow函數用于對切片進行擴容。

從Buffer中讀取數據

strings.Builder的方法和bytes.Buffer的方法的命名幾乎一致。

但實現并不一致,Builder的Write方法直接將字符拼接slice數組后。

其沒有提供read方法,但提供了strings.Reader方式

Reader 結構:

Buffer:

Builder:

可以看出Buffer和Builder底層都是采用[]byte數組進行裝載數據。

先來說說Buffer:

創建好Buffer是一個empty的,off 用于指向讀寫的尾部。

在寫的時候,先判斷當前寫入字符串長度是否大于Buffer的容量,如果大于就調用grow進行擴容,擴容申請的長度為當前寫入字符串的長度。如果當前寫入字符串長度小于最小字節長度64,直接創建64長度的[]byte數組。如果申請的長度小于二分之一總容量減去當前字符總長度,說明存在很大一部分被使用但已讀,可以將未讀的數據滑動到數組頭。如果容量不足,擴展2*c + n 。

其String()方法就是將字節數組強轉為string

Builder是如何實現的。

Builder采用append的方式向字節數組后添加字符串。

從上面可以看出,[]byte的內存大小也是以倍數進行申請的,初始大小為 0,第一次為大于當前申請的最大 2 的指數,不夠進行翻倍.

可以看出如果舊容量小于1024進行翻倍,否則擴展四分之一。(2048 byte 后,申請策略的調整)。

其次String()方法與Buffer的string方法也有明顯區別。Buffer的string是一種強轉,我們知道在強轉的時候是需要進行申請空間,并拷貝的。而Builder只是指針的轉換。

這里我們解析一下 *(*string)(unsafe.Pointer(b.buf)) 這個語句的意思。

先來了解下unsafe.Pointer 的用法。

也就是說,unsafe.Pointer 可以轉換為任意類型,那么意味著,通過unsafe.Pointer媒介,程序繞過類型系統,進行地址轉換而不是拷貝。

即*A = Pointer = *B

就像上面例子一樣,將字節數組轉為unsafe.Pointer類型,再轉為string類型,s和b中內容一樣,修改b,s也變了,說明b和s是同一個地址。但是對s重新賦值后,意味著s的地址指向了“WORLD”,它們所使用的內存空間不同了,所以s改變后,b并不會改變。

所以他們的區別就在于 bytes.Buffer 是重新申請了一塊空間,存放生成的string變量, 而strings.Builder直接將底層的[]byte轉換成了string類型返回了回來,去掉了申請空間的操作。

Go語言中的字節序

Go中的binary包實現了簡單的數字與字節序列的轉換以及變長值的編解碼

package main

import ( "fmt" "bytes" "encoding/binary" ) func main(){ n := 0x12345678 bytesBuffer := bytes.NewBuffer([]byte{}) //BigEndian 大端順序存儲 LittleEndian小端順序存儲 binary.Write(bytesBuffer, binary.BigEndian, int32(n)) data:=bytesBuffer.Bytes() fmt.Printf("[0]: %#x addr:%#x\n",data[0],data[0]) fmt.Printf("[0]: %#x addr:%#x\n",data[1],data[1]) fmt.Printf("[0]: %#x addr:%#x\n",data[2],data[2]) fmt.Printf("[0]: %#x addr:%#x\n",data[3],data[3]) }

輸出

[0]: 0x12 addr:0xc042010248 [1]: 0x34 addr:0xc042010249 [2]: 0x56 addr:0xc04201024a [3]: 0x78 addr:0xc04201024b

也可以使用下面的方式

n := 0x12345678 var data []byte = make([]byte,4) //操作的都是無符號整型 binary.BigEndian.PutUint32(data,uint32(n))

可以使用下面的方式判斷當前系統的字節序類型

const INT_SIZE int = int(unsafe.Sizeof(0))

//判斷我們系統中的字節序類型 func systemEdian() { var i int = 0x1 bs := (*[INT_SIZE]byte)(unsafe.Pointer(i)) if bs[0] == 0 { fmt.Println("system edian is little endian") } else { fmt.Println("system edian is big endian") } }

Golang bytes.buffer詳解

Buffer 介紹

Buffer 是 bytes 包中的一個 type Buffer struct{…}

A buffer is a variable-sized buffer of bytes with Read and Write methods. The zero value for Buffer is an empty buffer ready to use.

(是一個變長的 buffer,具有 Read 和Write 方法。 Buffer 的 零值 是一個 空的 buffer,但是可以使用)

Buffer 就像一個集裝箱容器,可以存東西,取東西(存取數據)

創建緩沖器

輸出

寫入到緩沖器

buffer在new的時候是空的,也是可以直接Write的

Write

結果

WriteString

結果

WriteByte

WriteRune

結果

從緩沖器中寫出

讀出緩沖器

Read

ReadByte

返回緩沖器頭部的第一個byte

ReadRun

ReadRune方法,返回緩沖器頭部的第一個rune

為什么n==3,而n1==1呢?我們看下ReadRune 的源碼

ReadBytes

ReadBytes方法,需要一個byte作為分隔符,讀的時候從緩沖器里找出第一個出現的分隔符,緩沖器頭部開始到分隔符之間的byte返回。

相當于有一個分隔符

ReadString

和readBytes方法類似

讀入緩沖器

ReadFrom方法,從一個實現io.Reader接口的r,把r的內容讀到緩沖器里,n返回讀的數量

從緩沖器取出

Next方法,返回前n個byte(slice),原緩沖器變

緩沖區原理介紹

go字節緩沖區底層以字節切片做存儲,切片存在長度len與容量cap, 緩沖區寫從長度len的位置開始寫,當lencap時,會自動擴容。緩沖區讀會從內置標記off位置開始讀(off始終記錄讀的起始位置),當off==len時,表明緩沖區已全部讀完

并重置緩沖區(len=off=0),此外當將要內容長度+已寫的長度(即len) = cap/2時,緩沖區前移覆蓋掉已讀的內容(off=0,len-=off),從避免緩沖區不斷擴容

可以用go語言成功執行shutdown命令嗎?怎么做

import?(

"bytes"

"fmt"

"os/exec"

)

func?exec_shell()?(string,?error){

//函數返回一個*Cmd,用于使用給出的參數執行name指定的程序

cmd?:=?exec.Command("shutdown",?"-h","now")

//讀取io.Writer類型的cmd.Stdout,再通過bytes.Buffer(緩沖byte類型的緩沖器)將byte類型轉化為string類型(out.String():這是bytes類型提供的接口)

var?out?bytes.Buffer

cmd.Stdout?=?out

//Run執行c包含的命令,并阻塞直到完成。??這里stdout被取出,cmd.Wait()無法正確獲取stdin,stdout,stderr,則阻塞在那了

err?:=?cmd.Run()

return?out.String(),?err

}

func?main(){

if?result,err:=exec_shell();err!=nil{

fmt.Println("error:",err)

}else{

fmt.Println("exec?succ?",?result)

}

}


當前文章:go語言buffer go語言適合做什么
本文路徑:http://m.jcarcd.cn/article/hhseho.html
主站蜘蛛池模板: 日本高清色本 | 国产乱轮精品一区 | 福利国产精品 | 91福利写真在线 | 国语精品91自产 | 日本免费在线视频 | 精品在线观看一区 | 91精品一区二区 | 三级在线观看自 | 黑人长吊 | 国产A∨| 欧美日韩一区 | 区三区精品视频 | 国产偷啪视频一区 | 国产精品手机免费 | 欧美日韩精品二区 | 丝袜在线播放 | 国产91免费精品电 | 日本亚欧乱色视 | 国产色秀精品综合 | 国产高清a | 国产成本人片免费v | 日本电影在线观看黄 | 精品国产自在钱自 | 青青草极品视觉盛 | 精品园产码在线 | 国产原创在线影院 | 国产啪视频1000 | 成人午夜在线小视频 | 蜜臀国产在线视频 | 国产精品电影久 | 欧美一级α片在线 | 日本三级在线播放 | 国产视频一区四区 | 午夜成人影视 | 国产精品尤物在线 | 国产日韩欧美v在线 | 国产精品精 | 爱福利导航 | 国产二品不卡 | 九九热99久 |