io是 Go 语言标准库中处理 I/O 操作的核心模块,它定义了许多接口和实用函数,用于处理各种输入输出操作。下面我将详细介绍 io
模块的主要功能,并提供相应的代码示例。
1. 核心接口
1.1 io.Reader
接口
type Reader interface {Read(p []byte) (n int, err error)
}
示例:从字符串读取数据
package mainimport ("fmt""io""strings"
)func main() {reader := strings.NewReader("Hello, Reader!")buf := make([]byte, 8)for {n, err := reader.Read(buf)fmt.Printf("n = %v, err = %v, buf = %v\n", n, err, buf[:n])if err == io.EOF {break}}
}
1.2 io.Writer
接口
type Writer interface {Write(p []byte) (n int, err error)
}
示例:写入缓冲区
package mainimport ("fmt""io""os"
)func main() {file, err := os.Create("output.txt")if err != nil {fmt.Println("Error creating file:", err)return}defer file.Close()n, err := io.WriteString(file, "Hello, Writer!")if err != nil {fmt.Println("Error writing to file:", err)return}fmt.Printf("Wrote %d bytes\n", n)
}
1.3 io.Closer
接口
type Closer interface {Close() error
}
示例:资源清理
package mainimport ("fmt""io""os"
)func processFile(filename string) error {file, err := os.Open(filename)if err != nil {return err}defer file.Close() // 确保文件被关闭// 处理文件内容buf := make([]byte, 1024)for {_, err := file.Read(buf)if err == io.EOF {break}if err != nil {return err}// 处理数据...}return nil
}func main() {err := processFile("example.txt")if err != nil {fmt.Println("Error:", err)}
}
1.4 io.Seeker
接口
type Seeker interface {Seek(offset int64, whence int) (int64, error)
}
示例:文件随机访问
package mainimport ("fmt""io""os"
)func main() {file, err := os.Open("example.txt")if err != nil {fmt.Println("Error:", err)return}defer file.Close()// 移动到文件末尾_, err = file.Seek(0, io.SeekEnd)if err != nil {fmt.Println("Error seeking:", err)return}// 获取文件大小size, err := file.Seek(0, io.SeekCurrent)if err != nil {fmt.Println("Error getting size:", err)return}fmt.Printf("File size: %d bytes\n", size)// 回到文件开头_, err = file.Seek(0, io.SeekStart)if err != nil {fmt.Println("Error seeking:", err)return}// 读取前10个字节buf := make([]byte, 10)n, err := file.Read(buf)if err != nil {fmt.Println("Error reading:", err)return}fmt.Printf("Read %d bytes: %q\n", n, buf[:n])
}
2. 组合接口
2.1 io.ReadWriter
type ReadWriter interface {ReaderWriter
}
2.2 io.ReadCloser
type ReadCloser interface {ReaderCloser
}
2.3 io.WriteCloser
type WriteCloser interface {WriterCloser
}
2.4 io.ReadSeeker
type ReadSeeker interface {ReaderSeeker
}
2.5 io.ReadWriteSeeker
type ReadWriteSeeker interface {ReaderWriterSeeker
}
示例:使用 io.ReadWriteSeeker
package mainimport ("fmt""io""strings"
)func main() {var rw io.ReadWriteSeeker = &strings.Builder{}// 写入数据_, err := rw.Write([]byte("Hello, World!"))if err != nil {fmt.Println("Error writing:", err)return}// 回到开头_, err = rw.Seek(0, io.SeekStart)if err != nil {fmt.Println("Error seeking:", err)return}// 读取数据buf := make([]byte, 5)n, err := rw.Read(buf)if err != nil {fmt.Println("Error reading:", err)return}fmt.Printf("Read %d bytes: %q\n", n, buf[:n])
}
3. 实用函数
3.1 io.Copy
func Copy(dst Writer, src Reader) (written int64, err error)
示例:文件复制
package mainimport ("fmt""io""os"
)func main() {srcFile, err := os.Open("source.txt")if err != nil {fmt.Println("Error opening source file:", err)return}defer srcFile.Close()dstFile, err := os.Create("destination.txt")if err != nil {fmt.Println("Error creating destination file:", err)return}defer dstFile.Close()bytesCopied, err := io.Copy(dstFile, srcFile)if err != nil {fmt.Println("Error copying file:", err)return}fmt.Printf("Copied %d bytes\n", bytesCopied)
}
3.2 io.CopyN
func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
示例:限制复制字节数
package mainimport ("fmt""io""strings"
)func main() {src := strings.NewReader("This is a long string that we will copy partially")dst := &strings.Builder{}bytesCopied, err := io.CopyN(dst, src, 10)if err != nil {fmt.Println("Error:", err)return}fmt.Printf("Copied %d bytes: %q\n", bytesCopied, dst.String())
}
3.3 io.ReadAll
func ReadAll(r Reader) ([]byte, error)
示例:读取所有数据
package mainimport ("fmt""io""strings"
)func main() {r := strings.NewReader("Go is an open source programming language")data, err := io.ReadAll(r)if err != nil {fmt.Println("Error:", err)return}fmt.Printf("Read %d bytes: %q\n", len(data), data)
}
3.4 io.ReadAtLeast
func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
示例:确保读取足够数据
package mainimport ("fmt""io""strings"
)func main() {r := strings.NewReader("Hello, World!")buf := make([]byte, 10)n, err := io.ReadAtLeast(r, buf, 5)if err != nil {fmt.Println("Error:", err)return}fmt.Printf("Read at least %d bytes: %q\n", n, buf[:n])
}
3.5 io.WriteString
func WriteString(w Writer, s string) (n int, err error)
示例:写入字符串
package mainimport ("fmt""io""os"
)func main() {file, err := os.Create("output.txt")if err != nil {fmt.Println("Error:", err)return}defer file.Close()n, err := io.WriteString(file, "Hello, Go!")if err != nil {fmt.Println("Error:", err)return}fmt.Printf("Wrote %d bytes\n", n)
}
4. 高级功能
4.1 io.Pipe
func Pipe() (*PipeReader, *PipeWriter)
示例:管道通信
package mainimport ("fmt""io""time"
)func main() {r, w := io.Pipe()// 写入协程go func() {defer w.Close()for i := 0; i < 3; i++ {fmt.Fprintf(w, "Message %d\n", i)time.Sleep(time.Second)}}()// 读取协程go func() {buf := make([]byte, 1024)for {n, err := r.Read(buf)if err != nil {if err == io.EOF {fmt.Println("End of pipe")} else {fmt.Println("Error:", err)}return}fmt.Print("Received: ", string(buf[:n]))}}()time.Sleep(4 * time.Second)
}
4.2 io.TeeReader
func TeeReader(r Reader, w Writer) Reader
示例:读取同时写入
package mainimport ("fmt""io""os""strings"
)func main() {r := strings.NewReader("Hello, TeeReader!")var buf strings.Buildertee := io.TeeReader(r, &buf)// 从 tee 读取数据data, err := io.ReadAll(tee)if err != nil {fmt.Println("Error:", err)return}fmt.Println("Read from tee:", string(data))fmt.Println("Written to buffer:", buf.String())
}
4.3 io.MultiReader
func MultiReader(readers ...Reader) Reader
示例:合并多个读取器
package mainimport ("fmt""io""strings"
)func main() {r1 := strings.NewReader("Hello, ")r2 := strings.NewReader("MultiReader!")r3 := strings.NewReader(" How are you?")multi := io.MultiReader(r1, r2, r3)data, err := io.ReadAll(multi)if err != nil {fmt.Println("Error:", err)return}fmt.Println(string(data))
}
4.4 io.MultiWriter
func MultiWriter(writers ...Writer) Writer
示例:同时写入多个目标
package mainimport ("fmt""io""os"
)func main() {file, err := os.Create("output.txt")if err != nil {fmt.Println("Error:", err)return}defer file.Close()multi := io.MultiWriter(os.Stdout, file)fmt.Fprintln(multi, "This will be written to both stdout and the file")
}
5. 实用类型
5.1 io.LimitedReader
type LimitedReader struct {R Reader // underlying readerN int64 // max bytes remaining
}
示例:限制读取字节数
package mainimport ("fmt""io""strings"
)func main() {r := strings.NewReader("This is a long string")lr := &io.LimitedReader{R: r, N: 10}buf := make([]byte, 20)n, err := lr.Read(buf)if err != nil {fmt.Println("Error:", err)return}fmt.Printf("Read %d bytes: %q\n", n, buf[:n])
}
5.2 io.SectionReader
type SectionReader struct {// contains filtered or unexported fields
}
示例:读取文件部分内容
package mainimport ("fmt""io""os"
)func main() {file, err := os.Open("example.txt")if err != nil {fmt.Println("Error:", err)return}defer file.Close()// 创建一个 SectionReader,从第10字节开始,读取20字节section := io.NewSectionReader(file, 10, 20)data, err := io.ReadAll(section)if err != nil {fmt.Println("Error:", err)return}fmt.Println(string(data))
}
6. 错误处理
6.1 io.EOF
var EOF = errors.New("EOF")
示例:正确处理 EOF
package mainimport ("fmt""io""strings"
)func main() {r := strings.NewReader("Hello")buf := make([]byte, 10)for {n, err := r.Read(buf)fmt.Printf("n = %d, err = %v\n", n, err)if err == io.EOF {fmt.Println("Reached end of input")break}if err != nil {fmt.Println("Error:", err)break}fmt.Printf("Read %q\n", buf[:n])}
}
6.2 io.ErrClosedPipe
var ErrClosedPipe = errors.New("io: read/write on closed pipe")
示例:处理管道关闭错误
package mainimport ("fmt""io"
)func main() {r, w := io.Pipe()// 关闭写入端w.Close()_, err := w.Write([]byte("test"))if err == io.ErrClosedPipe {fmt.Println("Cannot write to closed pipe")} else if err != nil {fmt.Println("Other error:", err)}_, err = r.Read(make([]byte, 10))if err == io.EOF {fmt.Println("Read from closed pipe returns EOF")}
}
总结
Go 语言的 io
模块提供了:
- 一组简洁而强大的接口(
Reader
,Writer
,Closer
,Seeker
等) - 多种组合接口满足不同场景需求
- 丰富的实用函数(
Copy
,ReadAll
,WriteString
等) - 高级功能如管道、多路读写等
- 完善的错误处理机制
通过合理使用这些接口和函数,可以构建高效、灵活的 I/O 处理逻辑,同时保持代码的简洁性和可维护性。