# README
IO
Reader
接口的定义:
type Reader interface {
Read(p []byte) (n int, err error)
}
Read
将 len(p)
个字节读取到 p
中。它返回读取的字节数 n
(0 <= n <= len(p)
) 以及任何遇到的错误。
即使 Read
返回的 n < len(p)
,它也会在调用过程中占用 len(p)
个字节作为暂存空间。若可读取的数据不到 len(p)
个字节,Read
会
返回可用数据,而不是等待更多数据。
注意:Read
在成功读取 n > 0
个字节,如果遇到一个错误或 EOF
(end-of-file
),就会返回读取的字节数。所以在处理 IO 错误前,应该先处理读取
到的数据,如:
func ReadFrom(reader io.Reader, num int) ([]byte, error) {
p := make([]byte, num)
n, err := reader.Read(p)
if n > 0 {
return p[:n], nil
}
return p, err
}
Writer
接口的定义:
type Writer interface {
Write(p []byte) (n int, err error)
}
Write
将 len(p)
个字节从 p
中写入到基本数据流中。返回从 p
中被写入的字节数 n
(0 <= n <= len(p)
)以及任何遇到的引起写入提前
停止的错误。若 Write
返回的 n < len(p)
,它就必须返回一个 非 nil
的错误。
fmt
标准库中,有一组函数:Fprint/Fprintf/Fprintln
,第一个参数 io.Wrtier
类型,也就是说将数据格式化输出到 io.Writer
中。
先看 fmt.Println
函数的源码。
func Println(a ...interface{}) (n int, err error) {
return Fprintln(os.Stdout, a...)
}
fmt.Println
会将内容输出到标准输出中。
实现 Reader 和 Writer 接口的类型:
os.File
同时实现了io.Reader
和io.Writer
strings.Reader
实现了io.Reader
bufio.Reader/Writer
分别实现了io.Reader
和io.Writer
bytes.Buffer
同时实现了io.Reader
和io.Writer
bytes.Reader
实现了io.Reader
compress/gzip.Reader/Writer
分别实现了io.Reader
和io.Writer
crypto/cipher.StreamReader/StreamWriter
分别实现了io.Reader
和io.Writer
crypto/tls.Conn
同时实现了io.Reader
和io.Writer
encoding/csv.Reader/Writer
分别实现了io.Reader
和io.Writer
mime/multipart.Part
实现了io.Reader
net/conn
分别实现了io.Reader
和io.Writer
ReaderAt 接口的定义:
type ReaderAt interface {
ReadAt(p []byte, off int64) (n int, err error)
}
ReadAt
从基本输入源的偏移量 off
处开始,将 len(p)
个字节读取到 p
中。它返回读取的字节数 n
(0 <= n <= len(p)
)以及任何遇到的错误。
当 ReadAt
返回的 n < len(p)
时,它就会返回一个 非 nil
的错误来解释为什么没有返回更多的字节。ReadAt
比 Read
更严格。
即使 ReadAt
返回的 n < len(p)
,它也会在调用过程中使用 p
的全部作为暂存空间。若可读取的数据不到 len(p)
字节,ReadAt
就会阻塞,直
到所有数据都可用或一个错误发生。
若 n = len(p)
个字节从输入源的结尾处由 ReadAt
返回,Read
可能返回 err == EOF
或者 err == nil
。
reader := strings.NewReader("example.v1")
p := make([]byte, 6)
n, err := reader.ReadAt(p, 2)
if err != nil {
panic(err)
}
fmt.Printf("%s, %d\n", p, n) // ample., 6
WriterAt 接口的定义:
type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}
WriteAt
从 p
中将 len(p)
个字节写入到偏移量 off
处的基本数据流中。它返回从 p
中被写入的字节数 n
(0 <= n <= len(p)
)以及任何遇到的引起写入提
前停止的错误。若 WriteAt
返回的 n < len(p)
,它就必须返回一个 非 nil
的错误。
若被写区域没有重叠,可对相同的目标并行执行 WriteAt
调用。
file, err := os.Create("writeAt.txt")
if err != nil {
panic(err)
}
defer file.Close()
file.WriteString("hello, overwrite")
n, err := file.WriteAt([]byte("example.v1"), 7)
if err != nil {
panic(err)
}
fmt.Println(n) // 10
writeAt.txt
中的内容: hello, example.v1
。
运行示例:
go run main.go reader.go writer.go