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
