io 套件定義了 Go 的 I/O 操作核心介面。Go 的 I/O 設計遵循「小介面」原則,透過組合這些基本介面,可以彈性描述各種 I/O 能力。
核心介面#
// 讀取介面
type Reader interface {
Read(p []byte) (n int, err error)
}
// 寫入介面
type Writer interface {
Write(p []byte) (n int, err error)
}
// 關閉介面
type Closer interface {
Close() error
}
// 組合介面
type ReadWriter interface {
Reader
Writer
}
type ReadCloser interface {
Reader
Closer
}
type WriteCloser interface {
Writer
Closer
}
type ReadWriteCloser interface {
Reader
Writer
Closer
}io.Reader 詳解#
// Read 方法契約:
// - 讀取最多 len(p) 位元組到 p
// - 回傳讀取的位元組數 n(0 <= n <= len(p))
// - 到達結尾時回傳 n, io.EOF
// - 可能同時回傳資料和錯誤
func ReadAll(r io.Reader) ([]byte, error) {
var result []byte
buf := make([]byte, 1024)
for {
n, err := r.Read(buf)
if n > 0 {
result = append(result, buf[:n]...)
}
if err == io.EOF {
break
}
if err != nil {
return nil, err
}
}
return result, nil
}常見 io.Reader 實作
| 型別 | 說明 |
|---|---|
*os.File | 檔案讀取 |
*strings.Reader | 從字串讀取 |
*bytes.Reader | 從位元組切片讀取 |
*bytes.Buffer | 從緩衝區讀取 |
net.Conn | 網路連線讀取 |
*http.Response.Body | HTTP 回應讀取 |
*gzip.Reader | 解壓縮讀取 |
io.Writer 詳解#
// Write 方法契約:
// - 把 p 中的資料寫入底層資料流
// - 回傳寫入的位元組數 n(0 <= n <= len(p))
// - 若 n < len(p),必須回傳非 nil 的錯誤
type UpperWriter struct {
w io.Writer
}
func (u *UpperWriter) Write(p []byte) (int, error) {
upper := bytes.ToUpper(p)
return u.w.Write(upper)
}
// 使用
var buf bytes.Buffer
uw := &UpperWriter{w: &buf}
uw.Write([]byte("hello"))
fmt.Println(buf.String()) // "HELLO"實用 I/O 函式#
import "io"
// 複製資料
n, err := io.Copy(dst, src) // 完整複製
n, err := io.CopyN(dst, src, 1024) // 複製 1024 位元組
// 讀取全部
data, err := io.ReadAll(reader)
// 寫入字串
n, err := io.WriteString(writer, "hello")
// 讀取指定數量
buf := make([]byte, 10)
n, err := io.ReadFull(reader, buf) // 必須讀滿 10 位元組
// 限制讀取
limitedReader := io.LimitReader(reader, 1024) // 最多讀 1024 位元組
// 多重讀取
tee := io.TeeReader(src, dst) // 讀取的同時寫入 dstio.Pipe#
建立同步的記憶體管道:
pr, pw := io.Pipe()
go func() {
defer pw.Close()
pw.Write([]byte("Hello from pipe"))
}()
data, _ := io.ReadAll(pr)
fmt.Println(string(data)) // "Hello from pipe"