日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Go编程技巧--io.Reader/Writer

發(fā)布時(shí)間:2023/12/19 编程问答 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Go编程技巧--io.Reader/Writer 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

Go原生的pkg中有一些核心的interface,其中io.Reader/Writer是比較常用的接口。很多原生的結(jié)構(gòu)都圍繞這個(gè)系列的接口展開,在實(shí)際的開發(fā)過程中,你會發(fā)現(xiàn)通過這個(gè)接口可以在多種不同的io類型之間進(jìn)行過渡和轉(zhuǎn)化。本文結(jié)合實(shí)際場景來總結(jié)一番。

總覽

圍繞io.Reader/Writer,有幾個(gè)常用的實(shí)現(xiàn):

  • net.Conn, os.Stdin, os.File: 網(wǎng)絡(luò)、標(biāo)準(zhǔn)輸入輸出、文件的流讀取
  • strings.Reader: 把字符串抽象成Reader
  • bytes.Reader: 把[]byte抽象成Reader
  • bytes.Buffer: 把[]byte抽象成Reader和Writer
  • bufio.Reader/Writer: 抽象成帶緩沖的流讀取(比如按行讀寫)

這些實(shí)現(xiàn)對于初學(xué)者來說其實(shí)比較難去記憶,在遇到實(shí)際問題的時(shí)候更是一臉蒙圈,不知如何是好。下面用實(shí)際的場景來舉例

場景舉例

0. base64編碼成字符串

encoding/base64包中:

func NewEncoder(enc *Encoding, w io.Writer) io.WriteCloser

這個(gè)用來做base64編碼,但是仔細(xì)觀察發(fā)現(xiàn),它需要一個(gè)io.Writer作為輸出目標(biāo),并用返回的WriteCloser的Write方法將結(jié)果寫入目標(biāo),下面是Go官方文檔的例子

input := []byte("foo\x00bar") encoder := base64.NewEncoder(base64.StdEncoding, os.Stdout) encoder.Write(input)

這個(gè)例子是將結(jié)果寫入到Stdout,如果我們希望得到一個(gè)字符串呢?觀察上面的圖,不然發(fā)現(xiàn)可以用bytes.Buffer作為目標(biāo)io.Writer:

input := []byte("foo\x00bar") buffer := new(bytes.Buffer) encoder := base64.NewEncoder(base64.StdEncoding, buffer) encoder.Write(input) fmt.Println(string(buffer.Bytes())

1. []byte和struct之間正反序列化

這種場景經(jīng)常用在基于字節(jié)的協(xié)議上,比如有一個(gè)具有固定長度的結(jié)構(gòu):

type Protocol struct {Version uint8BodyLen uint16Reserved [2]byteUnit uint8Value uint32 }

通過一個(gè)[]byte來反序列化得到這個(gè)Protocol,一種思路是遍歷這個(gè)[]byte,然后逐一賦值。其實(shí)在encoding/binary包中有個(gè)方便的方法:

func Read(r io.Reader, order ByteOrder, data interface{}) error

這個(gè)方法從一個(gè)io.Reader中讀取字節(jié),并已order指定的端模式,來給填充data(data需要是fixed-sized的結(jié)構(gòu)或者類型)。要用到這個(gè)方法首先要有一個(gè)io.Reader,從上面的圖中不難發(fā)現(xiàn),我們可以這么寫:

var p Protocol var bin []byte //... binary.Read(bytes.NewReader(bin), binary.LittleEndian, &p)

換句話說,我們將一個(gè)[]byte轉(zhuǎn)成了一個(gè)io.Reader。

反過來,我們需要將Protocol序列化得到[]byte,使用encoding/binary包中有個(gè)對應(yīng)的Write方法:

func Write(w io.Writer, order ByteOrder, data interface{}) error

通過將[]byte轉(zhuǎn)成一個(gè)io.Writer即可:

var p Protocol buffer := new(bytes.Buffer) //... binary.Writer(buffer, binary.LittleEndian, p) bin := buffer.Bytes()

2. 從流中按行讀取

比如對于常見的基于文本行的HTTP協(xié)議的讀取,我們需要將一個(gè)流按照行來讀取。本質(zhì)上,我們需要一個(gè)基于緩沖的讀寫機(jī)制(讀一些到緩沖,然后遍歷緩沖中我們關(guān)心的字節(jié)或字符)。在Go中有一個(gè)bufio的包可以實(shí)現(xiàn)帶緩沖的讀寫:

func NewReader(rd io.Reader) *Reader func (b *Reader) ReadString(delim byte) (string, error)

這個(gè)ReadString方法從io.Reader中讀取字符串,直到delim,就返回delim和之前的字符串。如果將delim設(shè)置為\n,相當(dāng)于按行來讀取了:

var conn net.Conn //... reader := NewReader(conn) for {line, err := reader.ReadString([]byte('\n'))//... }

花式技(zuo)巧(si)

string轉(zhuǎn)[]byte

a := "Hello, playground" fmt.Println([]byte(a))

等價(jià)于

a := "Hello, playground" buf := new(bytes.Buffer) buf.ReadFrom(strings.NewReader(a)) fmt.Println(buf.Bytes())

總結(jié)

以上是生活随笔為你收集整理的Go编程技巧--io.Reader/Writer的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。