這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
在使用Go語言的過程中,無論你是實現web應用程式,還是控制台輸入輸出,又或者是網路操作,不可避免的會遇到IO操作,使用到io.Reader和io.Writer介面。也也許對這兩個介面和相關的一些介面很熟悉了,但是你腦海裡確很難形成一個對io介面的繼承關係整天的概貌,原因在於godoc預設並沒有像javadoc一樣顯示官方庫繼承關係,這導致了我們對io介面的繼承關係記憶不深,在使用的時候還經常需要翻文檔加深記憶。本文試圖梳理清楚Go io介面的繼承關係,提供一個io介面的全貌。
io介面回顧
首先我們回顧一下幾個常用的io介面。標準庫的實現是將功能細分,每個最小粒度的功能定義成一個介面,然後介面可以組成成更多功能的介面。
最小粒度的介面
123 |
type Reader interface { Read(p []byte) (n int, err error)} |
123 |
type Writer interface { Write(p []byte) (n int, err error)} |
123 |
type Closer interface { Close() error} |
123 |
type Seeker interface { Seek(offset int64, whence int) (int64, error)} |
123 |
type ReaderFrom interface { ReadFrom(r Reader) (n int64, err error)} |
123 |
type WriterTo interface { WriteTo(w Writer) (n int64, err error)} |
123 |
type ReaderAt interface { ReadAt(p []byte, off int64) (n int, err error)} |
123 |
type WriterAt interface { WriteAt(p []byte, off int64) (n int, err error)} |
以及
123 |
type ByteReader interface { ReadByte() (byte, error)} |
123 |
type ByteWriter interface { WriteByte(c byte) error} |
ByteScanner比ByteReader多了一個UnreadByte方法。
1234 |
type ByteScanner interface { ByteReader UnreadByte() error} |
123 |
type RuneReader interface { ReadRune() (r rune, size int, err error)} |
1234 |
type RuneScanner interface { RuneReader UnreadRune() error} |
組合介面
Go標準庫還定義了一些由上面的單一職能的介面組合而成的介面。
1234 |
type ReadCloser interface { Reader Closer} |
1234 |
type ReadSeeker interface { Reader Seeker} |
1234 |
type ReadWriter interface { Reader Writer} |
12345 |
type ReadWriteCloser interface { Reader Writer Closer} |
12345 |
type ReadWriteSeeker interface { Reader Writer Seeker} |
1234 |
type WriteCloser interface { Writer Closer} |
1234 |
type WriteSeeker interface { Writer Seeker} |
從它們的定義上可以看出,它們是最小粒度的組合。
最小介面的擴充
有些結構體struct實現並且擴充了介面,這些結構體是。
1234 |
type LimitedReader struct { R Reader // underlying reader N int64 // max bytes remaining} |
123 |
type PipeReader struct { // contains filtered or unexported fields} |
123 |
type PipeWriter struct { // contains filtered or unexported fields} |
123 |
type SectionReader struct { // contains filtered or unexported fields} |
下面我會將它們的繼承關係畫出來。
一些輔助方法
一些輔助方法可以產生特殊類型的Reader或者Writer:
12345 |
func LimitReader(r Reader, n int64) Readerfunc MultiReader(readers ...Reader) Readerfunc TeeReader(r Reader, w Writer) Readerfunc MultiWriter(writers ...Writer) Writer |
繼承關係
當然,Go語言中並沒有Java中那樣的繼承關係,而是基於duck type形式實現,我用嘗試展示Go io介面的繼承關係。
其中黃色是 bufio 包下的類型,
綠色是 archive.tar 包下的類型,
藍色是 bytes 包下的類型,
粉紅色是 strings包下的類型,
紫色是 crypto.tls 包下的類型。
Rand是math.rand包下的類型。
File是os包下的內容。
`Rand`左邊的那個Reader是image.jpeg下的內容。
我們最常用的是包io、bytes、bufio下的類型,所以這幾個包下的類型要記牢,在第三庫中經常會出現它們的身影。
中並沒有把mime/multipart.File和 net/http.File列出來,主要是圖太複雜了,它們實現的介面和os.File類似。
當然你可能會問,你怎麼整理的它們的繼承關係?事實上,你可以通過godoc -analysis=type -http=:6060產生帶繼承關係的Go doc,並且它還可以將你本地下載的庫中的繼承關係也顯示出來。
參考文檔
- https://golang.org/pkg/io/
- https://golang.org/pkg/bufio/
- https://golang.org/pkg/bytes/
- https://medium.com/@benbjohnson/go-walkthrough-io-package-8ac5e95a9fbd#.er7vmwvb3
- https://medium.com/@blumenmann/a-simple-beginners-tutorial-to-io-writer-in-golang-2a13bfefea02#.sm0gq7rn0
- https://www.reddit.com/r/golang/comments/4z2eo2/noob_question_how_to_discover_interface/