?# 11.8 第二個(gè)例子:讀和寫
讀和寫是軟件中很普遍的行為,提起它們會(huì)立即想到讀寫文件、緩存(比如字節(jié)或字符串切片)、標(biāo)準(zhǔn)輸入輸出、標(biāo)準(zhǔn)錯(cuò)誤以及網(wǎng)絡(luò)連接、管道等等,或者讀寫我們的自定義類型。為了讓代碼盡可能通用,Go 采取了一致的方式來讀寫數(shù)據(jù)。
io
包提供了用于讀和寫的接口 io.Reader
和 io.Writer
:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
只要類型實(shí)現(xiàn)了讀寫接口,提供 Read()
和 Write
方法,就可以從它讀取數(shù)據(jù),或向它寫入數(shù)據(jù)。一個(gè)對象要是可讀的,它必須實(shí)現(xiàn) io.Reader
接口,這個(gè)接口只有一個(gè)簽名是 Read(p []byte) (n int, err error)
的方法,它從調(diào)用它的對象上讀取數(shù)據(jù),并把讀到的數(shù)據(jù)放入?yún)?shù)中的字節(jié)切片中,然后返回讀取的字節(jié)數(shù)和一個(gè) error
對象,如果沒有錯(cuò)誤發(fā)生返回 nil
,如果已經(jīng)到達(dá)輸入的尾端,會(huì)返回 io.EOF("EOF")
,如果讀取的過程中發(fā)生了錯(cuò)誤,就會(huì)返回具體的錯(cuò)誤信息。類似地,一個(gè)對象要是可寫的,它必須實(shí)現(xiàn) io.Writer
接口,這個(gè)接口也只有一個(gè)簽名是 Write(p []byte) (n int, err error)
的方法,它將指定字節(jié)切片中的數(shù)據(jù)寫入調(diào)用它的對象里,然后返回實(shí)際寫入的字節(jié)數(shù)和一個(gè) error
對象(如果沒有錯(cuò)誤發(fā)生就是 nil
)。
io
包里的 Readers
和 Writers
都是不帶緩沖的,bufio
包里提供了對應(yīng)的帶緩沖的操作,在讀寫 UTF-8
編碼的文本文件時(shí)它們尤其有用。在 第12章 我們會(huì)看到很多在實(shí)戰(zhàn)中使用它們的例子。
在實(shí)際編程中盡可能的使用這些接口,會(huì)使程序變得更通用,可以在任何實(shí)現(xiàn)了這些接口的類型上使用讀寫方法。
例如一個(gè) JPEG
圖形解碼器,通過一個(gè) Reader
參數(shù),它可以解碼來自磁盤、網(wǎng)絡(luò)連接或以 gzip
壓縮的 HTTP
流中的 JPEG
圖形數(shù)據(jù),或者其他任何實(shí)現(xiàn)了 Reader
接口的對象。