這是一個建立於 的文章,其中的資訊可能已經有所發展或是發生改變。
介紹
package io主要包含以下檔案:
- io.go 基礎的io操作,如讀寫,較底層
- multi.go 多個Reader封裝成一個
- pipe.go
- ioutil 常用操作
- ioutil.go 封裝了ioutil
- tempfile.go 有關建立臨時檔案
Reader & Writer
這兩個介面是用途最廣的介面之一,所以重點學習一下,後續會用在os,net等各種常用包。
io.Readertype Reader interface { Read(p []byte) (n int, err error)}io.Writertype Writer interface { Write(p []byte) (n int, err error)}
具體例子,以strings.Reader為例,代碼:
package strings...type Reader struct { s string i int64 // current reading index prevRune int // index of previous rune; or < 0}func (r *Reader) Read(b []byte) (n int, err error) { if r.i >= int64(len(r.s)) { return 0, io.EOF } r.prevRune = -1 n = copy(b, r.s[r.i:]) r.i += int64(n) return}
可見該類滿足io.Reader契約,所以使用時可以這樣(清晰起見,以顯式類型編碼):
var strReader io.Reader = strings.NewReader("hello")if _, err := io.Copy(os.Stdout, r); err != nil { log.Fatal(err)}
從源碼來看,
第一,實際上Reader就是封裝了序列化資料的一個容器。這一點從命名上來講可能不是那麼明顯,從名字上看,可能Reader只是一個調用者,需要從別的地方去『讀取』資料,實際上大部分Reader本身包括了資料。
第二,Reader類似我們現在的優酷馬鈴薯播放器,能夠記住上一次播放的位置,每次去觀看都從上次看的接著看。
Copy
這個方法從前面也能看到十分常用
func Copy(dst Writer, src Reader) (written int64, err error)
作用是將src的內容寫入到dst之中,
注意,在buildin中有一個copy方法與之類似,
func copy(dst, src []Type) int
只不過是處理[]byte類型。
查看io.Copy方法的源碼,我們發現其中調用了
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
並預設建立了一個buf,代碼如下
if buf == nil { buf = make([]byte, 32*1024)}
然後,內部調用了src.Read(buf),並在返回不為EOF的情況下將buf內容逐漸寫入dst。加上一些錯誤處理。
Copy方法還有一個兄弟:io.CopyN:
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
最多拷貝n個位元組。
與CopyN相反,還有一個方法:
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
該方法至少讀取min個位元組直到全部讀完,否則將拋異常。
這個方法主要用途是保證byte的內容被完整的讀取,見ReadFull:
func ReadFull(r Reader, buf []byte) (n int, err error) { return ReadAtLeast(r, buf, len(buf))}
io/ioutil
相比之下io中的偏底層實現,ioutil的方法更加實用,常用方法有:
func ReadAll(r io.Reader) ([]byte, error)
將reader中的所有內容讀取出來,返回位元組數組,不需要自己提供位元組數組
func ReadFile(filename string) ([]byte, error)
將一個檔案名稱傳入,返回內容位元組數組
func WriteFile(filename string, data []byte, perm os.FileMode)error
將data寫入檔案,如果檔案不存在,則以perm的模式建立檔案
func ReadDir(dirname string) ([]os.FileInfo, error)
返回目錄下的所有檔案資訊(個人認為這個方法出現得有點奇怪,應該在os包更合理)