天天看點

Golang 中的 io 包詳解(六):常用的可導出函數詳解

作者:路多辛

io.Copy

func Copy(dst Writer, src Reader) (written int64, err error)           

用于在 io.Reader 或 io.Writer 之間複制資料,接受兩個參數,一個 Writer 和一個 Reader。從 Reader 中讀取資料并寫入到 Writer 中,直到無法再從 Reader 中讀取到任何資料(EOF)或發生錯誤,傳回被複制的位元組數和任何發生的錯誤資訊。簡單的使用示例如下:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	src, err := os.Open("src.txt")
	if err != nil {
		panic(err)
	}
	defer src.Close()

	dst, err := os.Create("dst.txt")
	if err != nil {
		panic(err)
	}
	defer dst.Close()

	written, err := io.Copy(dst, src)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Copied %d bytes\n", written)
}
           

io.CopyBuffer

func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)           

用于在 io.Reader 和 io.Writer 之間緩沖複制資料,與 io.Copy 函數不同的是,使用 io.CopyBuffer 可以手動控制緩沖區的大小。如果 buf 為 nil,則配置設定一個;如果長度為零,則會觸發 panic。io.CopyBuffer 避免了 io.Copy 可能出現的大記憶體使用問題,因為可以使用具有固定大小的緩沖區,是以可以更好地控制記憶體使用、提高性能。簡單使用示例如下:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	src, err := os.Open("src.txt")
	if err != nil {
		panic(err)
	}
	defer src.Close()

	dst, err := os.Create("dst.txt")
	if err != nil {
		panic(err)
	}
	defer dst.Close()

	buf := make([]byte, 4)
	written, err := io.CopyBuffer(dst, src, buf)
	if err != nil {
		panic(err)
	}
	fmt.Printf("Copied %d bytes\n", written)
}           

io.CopyN

func CopyN(dst Writer, src Reader, n int64) (written int64, err error)           

用于從 io.Reader 中讀取指定數量的位元組數并寫入 io.Writer 中。與 io.Copy 函數不同的是,會從源 io.Reader 中讀取 n 個位元組并寫入到目标 io.Writer 中,從源讀入了指定數量的位元組資料後就會停止。簡單使用示例如下:

package main

import (
	"fmt"
	"io"
	"os"
)

func main() {
	src, err := os.Open("file.txt")
	if err != nil {
		panic(err)
	}
	defer src.Close()

	dst, err := os.Create("dst.txt")
	if err != nil {
		panic(err)
	}
	defer dst.Close()

	written, _ := io.CopyN(dst, src, 5)
	fmt.Printf("Copied %d bytes\n", written)
}           

io.LimitReader

func LimitReader(r Reader, n int64) Reader           

從 io.Reader 中讀取資料,最多傳回 n 個位元組。如果讀取資料時提前達到了這個限制,io.Reader 就會傳回 io.EOF 錯誤(表示已經讀取到了流的末尾)。簡單使用示例如下:

package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	data := "Hello, World!"
	reader := strings.NewReader(data)
	limit := int64(5)
	limitedReader := io.LimitReader(reader, limit)
	buf := make([]byte, limit)
	limitedReader.Read(buf)
	fmt.Printf("%s\n", buf) // 輸出: Hello
}           

io.ReadAll

func ReadAll(r Reader) ([]byte, error)           

用于讀取指定 io.Reader 中所有資料,不限制讀取資料的大小。簡單使用示例如下:

package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	r := strings.NewReader("路多辛的部落格,分享後端領域知識與經驗")
	b, err := io.ReadAll(r)
	if err != nil {
		panic(err)
	}
	fmt.Println(string(b))
}           

io.ReadAtLeast

func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)           

用于從 io.Reader 中讀取至少指定數量位元組的資料,會嘗試從 io.Reader 中讀取至少 min 個位元組,如果資料不足,會傳回一個無法讀取請求的位元組數錯誤。簡單使用示例如下:

package main

import (
	"fmt"
	"io"
	"log"
	"strings"
)

func main() {
	r := strings.NewReader("路多辛的部落格,分享後端領域知識與經驗")
	buf := make([]byte, 18)
	if _, err := io.ReadAtLeast(r, buf, 6); err != nil {
		log.Fatal(err)
	}
	fmt.Printf("%s\n", buf)


	shortBuf := make([]byte, 3)
	if _, err := io.ReadAtLeast(r, shortBuf, 4); err != nil {
		fmt.Println("error:", err)
	}


	longBuf := make([]byte, 64)
	if _, err := io.ReadAtLeast(r, longBuf, 64); err != nil {
		fmt.Println("error:", err)
	}
}           

io.ReadFull

func ReadFull(r Reader, buf []byte) (n int, err error)           

用于從 io.Reader 中讀取 len(buf)個位元組到 buf 中。如果資料不足,會傳回一個無法讀取請求的位元組數的錯誤。簡單使用示例如下:

package main

import (
	"fmt"
	"io"
	"strings"
)

func main() {
	r := strings.NewReader("路多辛的部落格,分享後端領域知識與經驗")

	buf := make([]byte, 18)
	if _, err := io.ReadFull(r, buf); err != nil {
		panic(err)
	}
	fmt.Println(string(buf))

	longBuf := make([]byte, 64)
	if _, err := io.ReadFull(r, longBuf); err != nil {
		panic(err)
	}
}