本文執行個體分析了GO語io包的常用介面。分享給大家供大家參考。具體分析如下:
我沒有 C/C++ 基礎,沒有介面的概念,且從 Python 投奔而來,Python 的極簡主義(一個結果往往只提供一個方法),讓我在 Golang 中非常迷糊,特別是檔案的讀寫操作,因為 Go 的檔案讀寫操作有很多的方法,讓我不知道怎麼選擇。直到我學習了 interface 的概念,然後由看了 package io 後才慢慢理解,也漸漸的喜歡上了 Golang 的靈活性。以我的經驗來說,介面是一個很重要的知識點,是一系列操作的規範,特別是公用介面尤為重要,如:package io
本文僅僅列舉最常用的幾個介面,如果您想系統的學習 io 介面,建議閱讀底部參考連結。
一、IO 介面概述
package os 提供了對 I/O 原語的基本介面,使之成為共用的公用介面,這些公用介面抽象出了泛用的函數並附加了一些相關的原語的操作。因為這些介面和原語是對底層實現完全不同的低水平操作的封裝,除非得到其它方面的通知,用戶端不應假設它們是並發執行安全的。
在 package os 中最重要的是兩個介面:Reader 和 Writer 介面。本章所提到的各種介面,都跟這兩個介面有關,也就是說,只要實現了這兩個介面,它就有了 IO 的功能。
小貼士:
var EOF = errors.New("EOF"): 在 package io中定義,使用非常頻繁。正常情況下當 Read() 無法得到更多返回時就返回 EOF,即檔案到達了結尾(end-of-file)。
二、io.Reader 和 io.Writer
定義:
複製代碼 代碼如下:
type Reader interface {
Read(p []byte) (n int, err error)
}
type Writer interface {
Write(p []byte) (n int, err error)
}
Read 將 len(p) 個位元組讀取到 p 中,當遇到任何錯誤(包括EOF)會立即返回已讀取的位元組數,函數結束會返回成功讀取的位元組數和任何錯誤。
Write 將 len(p) 位元組資料從 p 寫入底層的資料流,然後返回成功寫入的位元組數和任何錯誤。
從介面名稱很容易猜到,一般地,Go中介面的命名規範:介面名以er結尾。注意,這裡並非強行要求,你完全可以不以 er 結尾。標準庫中有些介面也不是以 er 結尾的。
樣本:
複製代碼 代碼如下:
func wr() {
f, _ := os.Create("at.txt")
defer f.Close()
f.Write([]byte("Go是一種令人愉悅的程式設計語言")) //寫入位元組流
f.Seek(0, os.SEEK_SET) //將指標重設
p := make([]byte, 2) // 讀取 2 byte( len(buf)=2 )
if _, err := f.Read(p); err != nil {
log.Fatal("[F]", err)
}
fmt.Printf("讀取字元 \"%s\", 長度為 %d byte\n", p, len(p))
p = make([]byte, 50)
if _, err := f.Read(p); err != nil {
if err != io.EOF { //忽略 EOF 錯誤
log.Fatal("[F]", err)
}
}
fmt.Printf("讀取字元 \"%s\", 長度為 %d byte\n", p, len(p))
}
讀取字元 "Go", 長度為 2 byte
讀取字元 "是一種令人愉悅的程式設計語言 ", 長度為 50 byte
三、io.ReaderAt 和 os.WriterAt
定義(off 是 offset 的縮寫):
複製代碼 代碼如下:
type ReaderAt interface {
ReadAt(p []byte, off int64) (n int, err error)
}
type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}
ReadAt() 從基本輸入源的位移量 off 處開始,其他和 Read() 一樣;
WriteAt() 從基本輸入源的位移量 off 處開始,其他和 Write() 一樣。
樣本:
複製代碼 代碼如下:
func at() {
f, _ := os.Create("at.txt")
defer f.Close()
f.WriteString("Go是一種令人愉悅的程式設計語言")
f.WriteAt([]byte("程式"), 26) //位移 26byte 改寫“編程”->“程式”
fi, _ := f.Stat() //擷取檔案資訊
p := make([]byte, fi.Size()-2) //檔案大小減去位移值
f.ReadAt(p, 2) //位移 2 byte
os.Stdout.Write(p)
}
四、io.ReaderFrom 和 os.WriterTo
定義:
複製代碼 代碼如下:
type ReaderFrom interface {
ReadFrom(r Reader) (n int64, err error)
}
type WriterTo interface {
WriteTo(w Writer) (n int64, err error)
}
ReadFrom() 從 r 中讀取資料,直到 EOF 或發生錯誤。返回讀取的位元組數和 io.EOF 之外的其他錯誤。ReadFrom不會返回EOF錯誤
WriteTo() 將資料寫入 w 中,直到沒有資料可寫或發生錯誤。返回寫入的位元組數和任何錯誤。
樣本:
複製代碼 代碼如下:
func fromTo() {
r := strings.NewReader("Go是一種令人愉悅的程式設計語言") //建立一個 Reader
w := bufio.NewWriter(os.Stdout) //建立一個 Writer
w.ReadFrom(r) // w 一次性讀取 r 的全部內容
w.Flush()
r.Seek(0, os.SEEK_SET) //重設指標
r.WriteTo(w) // r 一次性將內容寫入 w 中
w.Flush()
}
五、io.Seeker
定義:
複製代碼 代碼如下:
type Seeker interface {
Seek(offset int64, whence int) (ret int64, err error)
}
Seek 設定下一次 Read 或 Write 的位移量(offset),它的解釋取決於 whence。樣本見上文。
whence的值,在os包中定義了相應的常量:
複製代碼 代碼如下:
SEEK_SET int = 0 //從檔案的起始處開始設定 offset
SEEK_CUR int = 1 //從檔案的指標的當前位置處開始設定 offset
SEEK_END int = 2 //從檔案的末尾處開始設定 offset
六、io.Closer
定義:
複製代碼 代碼如下:
type Closer interface {
Close() error
}
用於關閉資料流,釋放資源,不用多廢話了吧。
七、其他
複製代碼 代碼如下:
type ByteReader interface {
ReadByte() (c byte, err error)
}
type RuneReader interface {
ReadRune() (r rune, size int, err error)
}
ReadByte讀取輸入中的單個位元組並返回。如果沒有位元組可讀取,會返回錯誤。
ReadRune讀取單個utf-8編碼的字元,返回該字元和它的位元組長度。如果沒有有效字元,會返回錯誤。
複製代碼 代碼如下:
type ByteWriter interface {
WriteByte(c byte) error
}
WriteByte寫入一個位元組,如果寫入失敗會返回錯誤。
參考:
https://gowalker.org/io
https://github.com/polaris1119/The-Golang-Standard-Library-by-Example/blob/master/chapter01/01.1.md
希望本文所述對大家的GO語言程式設計有所協助。