天天看點

如何在 Go 中将 []byte 轉換為 io.Reader?

原文連結: 如何在 Go 中将 []byte 轉換為 io.Reader?

如何在 Go 中将 []byte 轉換為 io.Reader?

在 stackoverflow 上看到一個問題,題主進行了一個網絡請求,接口傳回的是 <code>[]byte</code>。如果想要将其轉換成 <code>io.Reader</code>,需要怎麼做呢?

這個問題解決起來并不複雜,簡單幾行代碼就可以輕松将其轉換成功。不僅如此,還可以再通過幾行代碼反向轉換回來。

下面聽我慢慢給你吹,首先直接看兩段代碼。

輸出:

這段代碼先将 <code>[]byte</code> 資料轉換到 <code>reader</code> 中,然後再從 <code>reader</code> 中讀取資料,并列印輸出。

這段代碼先建立了一個 <code>reader</code>,然後讀取資料到 <code>buf</code>,最後列印輸出。

以上兩段代碼就是 <code>[]byte</code> 和 <code>io.Reader</code> 互相轉換的過程。對比這兩段代碼不難發現,都有 <code>NewReader</code> 的身影。而且在轉換過程中,都起到了關鍵作用。

那麼問題來了,這個 <code>NewReader</code> 到底是什麼呢?接下來我們通過源碼來一探究竟。

Go 的 <code>io</code> 包提供了最基本的 IO 接口,其中 <code>io.Reader</code> 和 <code>io.Writer</code> 兩個接口最為關鍵,很多原生結構都是圍繞這兩個接口展開的。

如何在 Go 中将 []byte 轉換為 io.Reader?

下面就來分别說說這兩個接口:

<code>io.Reader</code> 表示一個讀取器,它将資料從某個資源讀取到傳輸緩沖區。在緩沖區中,資料可以被流式傳輸和使用。

如何在 Go 中将 []byte 轉換為 io.Reader?

接口定義如下:

<code>Read()</code> 方法将 <code>len(p)</code> 個位元組讀取到 <code>p</code> 中。它傳回讀取的位元組數 <code>n</code>,以及發生錯誤時的錯誤資訊。

舉一個例子:

這段代碼從 <code>reader</code> 不斷讀取資料,每次讀 4 個位元組,然後列印輸出,直到結尾。

最後一次傳回的 n 值有可能小于緩沖區大小。

<code>io.Writer</code> 表示一個編寫器,它從緩沖區讀取資料,并将資料寫入目标資源。

如何在 Go 中将 []byte 轉換為 io.Reader?

<code>Write</code> 方法将 <code>len(p)</code> 個位元組從 <code>p</code> 中寫入到對象資料流中。它傳回從 <code>p</code> 中被寫入的位元組數 <code>n</code>,以及發生錯誤時傳回的錯誤資訊。

<code>bytes.Buffer</code> 是一個結構體類型,用來暫存寫入的資料,其實作了 <code>io.Writer</code> 接口的 <code>Write</code> 方法。

<code>WriteTo</code> 方法定義:

<code>WriteTo</code> 方法第一個參數是 <code>io.Writer</code> 接口類型。

再說回文章開頭的轉換問題。

隻要某個執行個體實作了接口 <code>io.Reader</code> 裡的方法 <code>Read()</code> ,就滿足了接口 <code>io.Reader</code>。

如何在 Go 中将 []byte 轉換為 io.Reader?

<code>bytes</code> 和 <code>strings</code> 包都實作了 <code>Read()</code> 方法。

在調用 <code>NewReader</code> 的時候,會傳回了對應的 <code>T.Reader</code> 類型,而它們都是通過 <code>io.Reader</code> 擴充而來的,是以也就實作了轉換。

在開發過程中,避免不了要進行一些 IO 操作,包括列印輸出,檔案讀寫,網絡連接配接等。

在 Go 語言中,也提供了一系列标準庫來應對這些操作,主要封裝在以下幾個包中:

<code>io</code>:基本的 IO 操作接口。

<code>io/ioutil</code>:封裝了一些實用的 IO 函數。

<code>fmt</code>:實作了 IO 格式化操作。

<code>bufio</code>:實作了帶緩沖的 IO。

<code>net.Conn</code>:網絡讀寫。

<code>os.Stdin</code>,<code>os.Stdout</code>:系統标準輸入輸出。

<code>os.File</code>:系統檔案操作。

<code>bytes</code>:位元組相關 IO 操作。

除了 <code>io.Reader</code> 和 <code>io.Writer</code> 之外,<code>io</code> 包還封裝了很多其他基本接口,比如 <code>ReaderAt</code>,<code>WriterAt</code>,<code>ReaderFrom</code> 和 <code>WriterTo</code> 等,這裡就不一一介紹了。這部分代碼并不複雜,讀起來很輕松,而且還能加深對接口的了解,推薦大家看看。

好了,本文就到這裡吧。關注我,帶你通過問題讀 Go 源碼。

推薦閱讀:

開始讀 Go 源碼了

熱情推薦:

計算機經典書籍(含下載下傳方式)

技術部落格: 硬核後端技術幹貨,内容包括 Python、Django、Docker、Go、Redis、ElasticSearch、Kafka、Linux 等。

Go 程式員: Go 學習路線圖,包括基礎專欄,進階專欄,源碼閱讀,實戰開發,面試刷題,必讀書單等一系列資源。

面試題彙總: 包括 Python、Go、Redis、MySQL、Kafka、資料結構、算法、程式設計、網絡等各種常考題。

參考文章:

https://books.studygolang.com/The-Golang-Standard-Library-by-Example/chapter01/01.1.html

https://www.cnblogs.com/jiujuan/p/14005731.html

https://segmentfault.com/a/1190000015591319