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!")) }
-
Pipe
Pipe
函数创建一对连接的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)) }
-
LimitedReader
LimitedReader
限制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)) }
-
MultiReader
MultiReader
连接多个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
和PipeWriter
PipeReader
和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)) }
-
TeeReader
TeeReader
同时将读取的数据写入另一个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.Copy
io.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.ReadAll
io.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.ReadFull
io.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.Seek
io.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.StringWriter
io.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
包有了全面的了解。掌握这些接口、类型和函数,可以帮助你在处理输入输出流时更高效、更灵活。