Go 的 io 包详细介绍
Go 的 io 包提供了基本的 I/O 原语和接口,用于处理输入和输出流。这个包定义了用于读写数据的基本接口,并提供了多种实现这些接口的工具和函数。
1. io 包接口和类型
-
Reader接口Reader接口是所有读取操作的基础,它定义了一个方法Read:package io type Reader interface { Read(p []byte) (n int, err error) }Read方法从数据源读取最多 len(p) 字节的数据到 p 中,并返回实际读取的字节数和可能的错误。示例:
package main import ( "fmt" "strings" "io" ) func main() { r := strings.NewReader("Hello, Go!") buf := make([]byte, 4) for { n, err := r.Read(buf) if err == io.EOF { break } if err != nil { fmt.Println("Error reading:", err) break } fmt.Printf("Read %d bytes: %s\n", n, string(buf[:n])) } } -
Writer接口Writer接口定义了一个方法Write:package io type Writer interface { Write(p []byte) (n int, err error) }Write方法将 p 中的数据写入到目标,并返回写入的字节数和可能的错误。示例:
package main import ( "fmt" "strings" "io" ) func main() { var w strings.Builder n, err := w.Write([]byte("Hello, Go!")) if err != nil { fmt.Println("Error writing:", err) return } fmt.Printf("Wrote %d bytes: %s\n", n, w.String()) } -
Closer接口Closer接口用于关闭资源,定义了一个方法Close:package io type Closer interface { Close() error }Close方法关闭资源,并返回可能的错误。 -
ReadWriter接口ReadWriter接口结合了Reader和Writer接口,定义了两个方法:package io type ReadWriter interface { Reader Writer }示例:
package main import ( "fmt" "io" "os" ) func main() { file, err := os.Create("example.txt") if err != nil { fmt.Println("Error creating file:", err) return } defer file.Close() rw := io.Writer(file) rw.Write([]byte("Hello, File!")) } -
PipePipe函数创建一对连接的Reader和Writer,它们可以用于在不同的协程之间传递数据。package io func Pipe() (*PipeReader, *PipeWriter)示例:
package main import ( "fmt" "io" "io/ioutil" ) func main() { pr, pw := io.Pipe() go func() { defer pw.Close() pw.Write([]byte("Hello, Pipe!")) }() data, err := ioutil.ReadAll(pr) if err != nil { fmt.Println("Error reading from pipe:", err) return } fmt.Println("Read from pipe:", string(data)) } -
LimitedReaderLimitedReader限制Reader读取的字节数:package io type LimitedReader struct { R Reader N int64 }示例:
package main import ( "fmt" "io" "strings" ) func main() { r := io.LimitReader(strings.NewReader("Hello, Go!"), 5) data, _ := io.ReadAll(r) fmt.Println("Limited read:", string(data)) } -
MultiReaderMultiReader连接多个Reader,依次读取每个Reader直到第一个读取完毕。package io type MultiReader struct { // contains filtered or unexported fields }示例:
package main import ( "fmt" "io" "strings" ) func main() { r1 := strings.NewReader("Hello, ") r2 := strings.NewReader("World!") mr := io.MultiReader(r1, r2) data, _ := io.ReadAll(mr) fmt.Println("Multi-read:", string(data)) } -
PipeReader和PipeWriterPipeReader和PipeWriter是Pipe函数返回的类型,它们用于在管道中进行读写操作。示例:
package main import ( "fmt" "io" ) func main() { pr, pw := io.Pipe() go func() { defer pw.Close() pw.Write([]byte("Hello, Pipe!")) }() data, err := io.ReadAll(pr) if err != nil { fmt.Println("Error reading from pipe:", err) return } fmt.Println("Read from pipe:", string(data)) } -
TeeReaderTeeReader同时将读取的数据写入另一个Writer并返回原始数据。package io type TeeReader struct { R Reader W Writer }示例:
package main import ( "fmt" "io" "strings" ) func main() { var output strings.Builder r := io.TeeReader(strings.NewReader("Hello, TeeReader!"), &output) data, _ := io.ReadAll(r) fmt.Println("Read data:", string(data)) fmt.Println("Written to output:", output.String()) }
2. 常用函数
-
io.Copyio.Copy从一个Reader复制数据到一个Writer。package io func Copy(dst Writer, src Reader) (written int64, err error)示例:
package main import ( "fmt" "io" "strings" ) func main() { src := strings.NewReader("Hello, Copy!") var dst strings.Builder _, err := io.Copy(&dst, src) if err != nil { fmt.Println("Error copying:", err) return } fmt.Println("Copied data:", dst.String()) } -
io.ReadAllio.ReadAll读取所有数据直到 EOF。package io func ReadAll(r Reader) ([]byte, error)示例:
package main import ( "fmt" "io" "strings" ) func main() { r := strings.NewReader("Hello, ReadAll!") data, err := io.ReadAll(r) if err != nil { fmt.Println("Error reading:", err) return } fmt.Println("Read all data:", string(data)) } -
io.ReadFullio.ReadFull读取指定长度的数据。package io func ReadFull(r Reader, buf []byte) (n int, err error)示例:
package main import ( "fmt" "io" "strings" ) func main() { r := strings.NewReader("Hello, ReadFull!") buf := make([]byte, 5) n, err := io.ReadFull(r, buf) if err != nil { fmt.Println("Error reading full data:", err) return } fmt.Printf("Read %d bytes: %s\n", n, string(buf)) } -
io.Seekio.Seek允许在Reader和Writer上设置当前位置(在实现了Seek接口的类型上使用)。示例:
package main import ( "fmt" "io" "os" ) func main() { file, err := os.Create("example.txt") if err != nil { fmt.Println
("Error creating file:", err) return } defer file.Close()
file.Write([]byte("Hello, Seek!"))
file.Seek(0, io.SeekStart)
buf := make([]byte, 5)
file.Read(buf)
fmt.Println("Seeked data:", string(buf))
}
5. **`io.StringReader`**
`io.StringReader` 允许将字符串视为 `Reader`。
```go
package io
func StringReader(s string) *strings.Reader
示例:
package main
import (
"fmt"
"io"
)
func main() {
r := io.StringReader("Hello, StringReader!")
data, _ := io.ReadAll(r)
fmt.Println("Read from StringReader:", string(data))
}
-
io.StringWriterio.StringWriter允许将Writer转换为字符串。示例:
package main import ( "fmt" "strings" "io" ) func main() { var sb strings.Builder w := io.StringWriter(&sb) w.Write([]byte("Hello, StringWriter!")) fmt.Println("Written data:", sb.String()) }
通过本章内容,你应该对 Go 的 io 包有了全面的了解。掌握这些接口、类型和函数,可以帮助你在处理输入输出流时更高效、更灵活。