介紹
package io主要包含以下文件:
- io.go 基礎(chǔ)的io操作岁经,如讀寫朋沮,較底層
- multi.go 多個Reader封裝成一個
- pipe.go
- ioutil 常用操作
- ioutil.go 封裝了ioutil
- tempfile.go 有關(guān)創(chuàng)建臨時文件
Reader & Writer
這兩個接口是用途最廣的接口之一,所以重點(diǎn)學(xué)習(xí)一下缀壤,后續(xù)會用在os樊拓,net等各種常用包。
io.Reader
type Reader interface {
Read(p []byte) (n int, err error)
}
io.Writer
type 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)
}
從源碼來看条篷,
第一,實(shí)際上Reader就是封裝了序列化數(shù)據(jù)的一個容器蛤织。這一點(diǎn)從命名上來講可能不是那么明顯赴叹,從名字上看,可能Reader只是一個調(diào)用者指蚜,需要從別的地方去『讀取』數(shù)據(jù)乞巧,實(shí)際上大部分Reader本身包括了數(shù)據(jù)。
第二摊鸡,Reader類似我們現(xiàn)在的優(yōu)酷土豆播放器摊欠,能夠記住上一次播放的位置丢烘,每次去觀看都從上次看的接著看。
Copy
這個方法從前面也能看到十分常用
func Copy(dst Writer, src Reader) (written int64, err error)
作用是將src的內(nèi)容寫入到dst之中些椒,
注意播瞳,在buildin中有一個copy方法與之類似,
func copy(dst, src []Type) int
只不過是處理[]byte類型免糕。
查看io.Copy方法的源碼赢乓,我們發(fā)現(xiàn)其中調(diào)用了
func copyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
并默認(rèn)創(chuàng)建了一個buf,代碼如下
if buf == nil {
buf = make([]byte, 32*1024)
}
然后石窑,內(nèi)部調(diào)用了src.Read(buf)牌芋,并在返回不為EOF的情況下將buf內(nèi)容逐漸寫入dst。加上一些錯誤處理松逊。
Copy方法還有一個兄弟:io.CopyN:
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
最多拷貝n個字節(jié)躺屁。
與CopyN相反,還有一個方法:
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
該方法至少讀取min個字節(jié)直到全部讀完经宏,否則將拋異常犀暑。
這個方法主要用途是保證byte的內(nèi)容被完整的讀取,見ReadFull:
func ReadFull(r Reader, buf []byte) (n int, err error) {
return ReadAtLeast(r, buf, len(buf))
}
io/ioutil
相比之下io中的偏底層實(shí)現(xiàn)烁兰,ioutil的方法更加實(shí)用耐亏,常用方法有:
func ReadAll(r io.Reader) ([]byte, error)
將reader中的所有內(nèi)容讀取出來,返回字節(jié)數(shù)組沪斟,不需要自己提供字節(jié)數(shù)組
func ReadFile(filename string) ([]byte, error)
將一個文件名傳入广辰,返回內(nèi)容字節(jié)數(shù)組
func WriteFile(filename string, data []byte, perm os.FileMode)
error
將data寫入文件,如果文件不存在主之,則以perm的模式創(chuàng)建文件
func ReadDir(dirname string) ([]os.FileInfo, error)
返回目錄下的所有文件信息(個人認(rèn)為這個方法出現(xiàn)得有點(diǎn)奇怪择吊,應(yīng)該在os包更合理)