Go語言標准庫_輸入/輸出


Go語言標准庫_輸入/輸出

轉載節選自《Go語言標准庫》

Reader 接口

type Reader interface {
    Read(p []byte) (n int, err error)
}

Read 將 len(p) 個字節讀取到 p 中。它返回讀取的字節數 n(0 <= n <= len(p)) 以及任何遇到的錯誤。即使 Read 返回的 n < len(p),它也會在調用過程中使用 p 的全部作為暫存空間。若一些數據可用但不到 len(p) 個字節,Read 會照例返回可用的數據,而不是等待更多數據。

當 Read 在成功讀取 n > 0 個字節后遇到一個錯誤或 EOF (end-of-file),它就會返回讀取的字節數。它會從相同的調用中返回(非nil的)錯誤或從隨后的調用中返回錯誤(同時 n == 0)。 一般情況的一個例子就是 Reader 在輸入流結束時會返回一個非零的字節數,同時返回的 err 不是 EOF 就是 nil。無論如何,下一個 Read 都應當返回 0, EOF。

調用者應當總在考慮到錯誤 err 前處理 n > 0 的字節。這樣做可以在讀取一些字節,以及允許的 EOF 行為后正確地處理 I/O 錯誤。

Writer

type Writer interface {
    Write(p []byte) (n int, err error)
}

Write 將 len(p) 個字節從 p 中寫入到基本數據流中。它返回從 p 中被寫入的字節數 n(0 <= n <= len(p))以及任何遇到的引起寫入提前停止的錯誤。若 Write 返回的 n < len(p),它就必須返回一個 非nil 的錯誤。

實現了 io.Reader 接口或 io.Writer 接口的類型

  • os.File 同時實現了 io.Reader 和 io.Writer
  • strings.Reader 實現了 io.Reader
  • bufio.Reader/Writer 分別實現了 io.Reader 和 io.Writer
  • bytes.Buffer 同時實現了 io.Reader 和 io.Writer
  • bytes.Reader 實現了 io.Reader
  • compress/gzip.Reader/Writer 分別實現了 io.Reader 和 io.Writer
  • crypto/cipher.StreamReader/StreamWriter 分別實現了 io.Reader 和 io.Writer
  • crypto/tls.Conn 同時實現了 io.Reader 和 io.Writer
  • encoding/csv.Reader/Writer 分別實現了 io.Reader 和 io.Writer
  • mime/multipart.Part 實現了 io.Reader

ReaderAt/WriterAt 接口

type ReaderAt interface {
    ReadAt(p []byte, off int64) (n int, err error)
}

ReadAt 從基本輸入源的偏移量 off 處開始,將 len(p) 個字節讀取到 p 中。它返回讀取的字節數 n(0 <= n <= len(p))以及任何遇到的錯誤。

當 ReadAt 返回的 n < len(p) 時,它就會返回一個 非nil 的錯誤來解釋 為什么沒有返回更多的字節。在這一點上,ReadAt 比 Read 更嚴格。

即使 ReadAt 返回的 n < len(p),它也會在調用過程中使用 p 的全部作為暫存空間。若一些數據可用但不到 len(p) 字節,ReadAt 就會阻塞直到所有數據都可用或產生一個錯誤。 在這一點上 ReadAt 不同於 Read。

若 n = len(p) 個字節在輸入源的的結尾處由 ReadAt 返回,那么這時 err == EOF 或者 err == nil。

若 ReadAt 按查找偏移量從輸入源讀取,ReadAt 應當既不影響基本查找偏移量也不被它所影響。

ReadAt 的客戶端可對相同的輸入源並行執行 ReadAt 調用。

type WriterAt interface {
    WriteAt(p []byte, off int64) (n int, err error)
}

WriteAt 從 p 中將 len(p) 個字節寫入到偏移量 off 處的基本數據流中。它返回從 p 中被寫入的字節數 n(0 <= n <= len(p))以及任何遇到的引起寫入提前停止的錯誤。若 WriteAt 返回的 n < len(p),它就必須返回一個 非nil 的錯誤。

若 WriteAt 按查找偏移量寫入到目標中,WriteAt 應當既不影響基本查找偏移量也不被它所影響。

若區域沒有重疊,WriteAt 的客戶端可對相同的目標並行執行 WriteAt 調用。

ReaderFrom/WriterTo 接口

type ReaderFrom interface {
    ReadFrom(r Reader) (n int64, err error)
}

ReadFrom 從 r 中讀取數據,直到 EOF 或發生錯誤。其返回值 n 為讀取的字節數。除 io.EOF 之外,在讀取過程中遇到的任何錯誤也將被返回。

如果 ReaderFrom 可用,Copy 函數就會使用它。

type WriterTo interface {
    WriteTo(w Writer) (n int64, err error)
}

WriteTo 將數據寫入 w 中,直到沒有數據可寫或發生錯誤。其返回值 n 為寫入的字節數。 在寫入過程中遇到的任何錯誤也將被返回。

如果 WriterTo 可用,Copy 函數就會使用它。

Seeker 接口

type Seeker interface {
    Seek(offset int64, whence int) (ret int64, err error)
}

Seek 設置下一次 Read 或 Write 的偏移量為 offset,它的解釋取決於 whence: 0 表示相對於文件的起始處,1 表示相對於當前的偏移,而 2 表示相對於其結尾處。 Seek 返回新的偏移量和一個錯誤,如果有的話。

whence 的值,在 os 包中定義了相應的常量,應該使用這些常量

const (
    SEEK_SET int = 0 // seek relative to the origin of the file
    SEEK_CUR int = 1 // seek relative to the current offset
    SEEK_END int = 2 // seek relative to the end
)

Closer接口

type Closer interface {
    Close() error
}

ByteReader 和 ByteWriter

type ByteReader interface {
    ReadByte() (c byte, err error)
}

type ByteWriter interface {
    WriteByte(c byte) error
}

在標准庫中,有如下類型實現了 io.ByteReader 或 io.ByteWriter:

  • bufio.Reader/Writer 分別實現了io.ByteReader 和 io.ByteWriter
  • bytes.Buffer 同時實現了 io.ByteReader 和 io.ByteWriter
  • bytes.Reader 實現了 io.ByteReader
  • strings.Reader 實現了 io.ByteReader

ByteScanner、RuneReader 和 RuneScanner

type ByteScanner interface {
    ByteReader
    UnreadByte() error
}

UnreadByte 方法的意思是:將上一次 ReadByte 的字節還原,使得再次調用 ReadByte 返回的結果和上一次調用相同,也就是說,UnreadByte 是重置上一次的 ReadByte。注意,UnreadByte 調用之前必須調用了 ReadByte,且不能連續調用 UnreadByte。

ReadCloser、ReadSeeker、ReadWriteCloser、ReadWriteSeeker、ReadWriter、WriteCloser 和 WriteSeeker 接口

這些接口是上面介紹的接口的兩個或三個組合而成的新接口。例如 ReadWriter 接口:

type ReadWriter interface {
    Reader
    Writer
}

SectionReader 類型

SectionReader 是一個 struct(沒有任何導出的字段),實現了 Read, Seek 和 ReadAt,同時,內嵌了 ReaderAt 接口。結構定義如下:

type SectionReader struct {
    r     ReaderAt    // 該類型最終的 Read/ReadAt 最終都是通過 r 的 ReadAt 實現
    base  int64        // NewSectionReader 會將 base 設置為 off
    off   int64        // 從 r 中的 off 偏移處開始讀取數據
    limit int64        // limit - off = SectionReader 流的長度
}

從名稱我們可以猜到,該類型讀取數據流中部分數據。看一下

func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader

的文檔說明就知道了:

NewSectionReader 返回一個 SectionReader,它從 r 中的偏移量 off 處讀取 n 個字節后以 EOF 停止。

PipeReader 和 PipeWriter 類型

PipeReader(一個沒有任何導出字段的 struct)是管道的讀取端。它實現了 io.Reader 和 io.Closer 接口。

關於 Read 方法的說明:從管道中讀取數據。該方法會堵塞,直到管道寫入端開始寫入數據或寫入端關閉了。如果寫入端關閉時帶上了 error(即調用 CloseWithError 關閉),該方法返回的 err 就是寫入端傳遞的error;否則 err 為 EOF。

PipeWriter(一個沒有任何導出字段的 struct)是管道的寫入端。它實現了 io.Writer 和 io.Closer 接口。

關於 Write 方法的說明:寫數據到管道中。該方法會堵塞,直到管道讀取端讀完所有數據或讀取端關閉了。如果讀取端關閉時帶上了 error(即調用 CloseWithError 關閉),該方法返回的 err 就是讀取端傳遞的error;否則 err 為 ErrClosedPipe。

Copy 和 CopyN 函數

func Copy(dst Writer, src Reader) (written int64, err error)

Copy 將 src 復制到 dst,直到在 src 上到達 EOF 或發生錯誤。它返回復制的字節數,如果有的話,還會返回在復制時遇到的第一個錯誤。

成功的 Copy 返回 err == nil,而非 err == EOF。由於 Copy 被定義為從 src 讀取直到 EOF 為止,因此它不會將來自 Read 的 EOF 當做錯誤來報告。

若 dst 實現了 ReaderFrom 接口,其復制操作可通過調用 dst.ReadFrom(src) 實現。此外,若 src 實現了 WriterTo 接口,其復制操作可通過調用 src.WriteTo(dst) 實現。

func CopyN(dst Writer, src Reader, n int64) (written int64, err error)

CopyN 將 n 個字節從 src 復制到 dst。 它返回復制的字節數以及在復制時遇到的最早的錯誤。由於 Read 可以返回要求的全部數量及一個錯誤(包括 EOF),因此 CopyN 也能如此。

若 dst 實現了 ReaderFrom 接口,復制操作也就會使用它來實現。

ReadAtLeast 和 ReadFull 函數

func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)

ReadAtLeast 將 r 讀取到 buf 中,直到讀了最少 min 個字節為止。它返回復制的字節數,如果讀取的字節較少,還會返回一個錯誤。若沒有讀取到字節,錯誤就只是 EOF。如果一個 EOF 發生在讀取了少於 min 個字節之后,ReadAtLeast 就會返回 ErrUnexpectedEOF。若 min 大於 buf 的長度,ReadAtLeast 就會返回 ErrShortBuffer。對於返回值,當且僅當 err == nil 時,才有 n >= min。

func ReadFull(r Reader, buf []byte) (n int, err error)

ReadFull 精確地從 r 中將 len(buf) 個字節讀取到 buf 中。它返回復制的字節數,如果讀取的字節較少,還會返回一個錯誤。若沒有讀取到字節,錯誤就只是 EOF。如果一個 EOF 發生在讀取了一些但不是所有的字節后,ReadFull 就會返回 ErrUnexpectedEOF。對於返回值,當且僅當 err == nil 時,才有 n == len(buf)。

WriteString 函數

func WriteString(w Writer, s string) (n int, err error)

MultiReader 和 MultiWriter 函數

這兩個函數的定義分別是:

func MultiReader(readers ...Reader) Reader
func MultiWriter(writers ...Writer) Writer

它們接收多個 Reader 或 Writer,返回一個 Reader 或 Writer。我們可以猜想到這兩個函數就是操作多個 Reader 或 Writer 就像操作一個。

TeeReader函數

func TeeReader(r Reader, w Writer) Reader


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM