io
io
https://pkg.go.dev/io@go1.20.1
io包提供了基本的I/O原语接口。它的主要任务是将这些原语的现有实现(例如os包中的实现)封装到共享的公共接口中,以抽象功能,以及一些其他相关的原语。
由于这些接口和原语封装了具有各种实现的底层操作,除非另有通知,否则客户端不应假设它们适合并行执行。
常量
1
2
3
4
5
| const (
SeekStart = 0 // 相对于文件的起点进行寻找
SeekCurrent = 1 // 相对于当前偏移量进行寻找
SeekEnd = 2 // 相对于结尾进行寻找
)
|
Seek whence values.
在Go语言中,Seek方法的whence参数用于确定相对于哪个位置进行偏移量的计算。
变量
1
| var EOF = errors.New("EOF")
|
EOF 是 Read方法在没有更多输入可用时返回的错误。(Read方法必须自己返回 EOF,而不是封装 EOF 的错误,因为调用者将使用 == 测试 EOF。)函数只应返回 EOF 来表示输入的优雅结束。如果 EOF 在结构化数据流中意外发生,则适当的错误是 ErrUnexpectedEOF 或提供更多详细信息的其他错误。
1
| var ErrClosedPipe = errors.New("io: read/write on closed pipe")
|
ErrClosedPipe是在关闭的管道上进行读取或写入操作时使用的错误。
1
| var ErrNoProgress = errors.New("multiple Read calls return no data or error")
|
ErrNoProgress 是一些 Reader 的客户端在多次调用 Read 后未返回任何数据或错误时返回的错误,通常表明 Reader 实现有问题。
1
| var ErrShortBuffer = errors.New("short buffer")
|
ErrShortBuffer表示读取所需的缓冲区比提供的缓冲区要长。
1
| var ErrShortWrite = errors.New("short write")
|
ErrShortWrite表示写入接受的字节数比请求的字节数少,但未返回明确的错误。
1
| var ErrUnexpectedEOF = errors.New("unexpected EOF")
|
ErrUnexpectedEOF表示在读取固定大小的块或数据结构的过程中遇到了EOF。
函数
func Copy
1
| func Copy(dst Writer, src Reader) (written int64, err error)
|
Copy函数从src复制到dst,直到在src上到达EOF或发生错误。它返回复制的字节数和在复制过程中遇到的第一个错误(如果有)。
成功的Copy返回err==nil,而不是err==EOF。因为Copy定义为从src读取直到EOF,所以它不会将从Read返回的EOF视为要报告的错误。
如果src实现了WriterTo接口,则通过调用src.WriteTo(dst)来实现复制。否则,如果dst实现了ReaderFrom接口,则通过调用dst.ReadFrom(src)来实现复制。【如果src和dst都实现了所说的,以哪个为准?】
Copy Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
if _, err := io.Copy(os.Stdout, r); err != nil {
log.Fatal(err)
}
}
Output:
some io.Reader stream to be read
|
func CopyBuffer <- go1.5
1
| func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)
|
CopyBuffer函数与Copy函数相同,只是它通过提供的缓冲区(如果需要)进行阶段处理,而不是分配临时缓冲区。如果buf为nil,则会分配一个;否则,如果长度为零,则CopyBuffer函数会出现panic。
如果src实现了WriterTo或dst实现了ReaderFrom,则不会使用buf执行复制。
CopyBuffer Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r1 := strings.NewReader("first reader\n")
r2 := strings.NewReader("second reader\n")
buf := make([]byte, 8)
// buf is used here...
if _, err := io.CopyBuffer(os.Stdout, r1, buf); err != nil {
log.Fatal(err)
}
// ... reused here also. No need to allocate an extra buffer.
if _, err := io.CopyBuffer(os.Stdout, r2, buf); err != nil {
log.Fatal(err)
}
}
Output:
first reader
second reader
|
func CopyN
1
| func CopyN(dst Writer, src Reader, n int64) (written int64, err error)
|
CopyN函数从src复制n个字节(或直到出现错误)到dst。它返回已复制的字节数和在复制过程中遇到的最早的错误。如果err == nil,则written == n。
如果dst实现了ReaderFrom接口,则使用它来实现复制。
CopyN Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read")
if _, err := io.CopyN(os.Stdout, r, 4); err != nil {
log.Fatal(err)
}
}
Output:
some
|
func Pipe
1
| func Pipe() (*PipeReader, *PipeWriter)
|
Pipe创建一个同步的内存管道。它可用于连接期望io.Reader的代码与期望io.Writer的代码。
在管道上的读取和写入是一对一匹配的,除非需要多个读取来消耗单个写入。也就是说,每次对PipeWriter的写入都会阻塞,直到它满足了来自PipeReader的一个或多个读取,这些读取完全消耗了已写入的数据。数据直接从写入到相应的读取(或读取)中复制;没有内部缓冲。
在并行调用Read和Write或与Close一起调用是安全的。并行调用Read和并行调用Write也是安全的:各个调用将依次进行。
Pipe Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| package main
import (
"fmt"
"io"
"log"
"os"
)
func main() {
r, w := io.Pipe()
go func() {
fmt.Fprint(w, "some io.Reader stream to be read\n")
w.Close()
}()
if _, err := io.Copy(os.Stdout, r); err != nil {
log.Fatal(err)
}
}
Output:
some io.Reader stream to be read
|
func ReadAll <- go1.16
1
| func ReadAll(r Reader) ([]byte, error)
|
ReadAll函数从r读取直到出现错误或EOF,并返回它读取的数据。成功调用返回err == nil,而不是err == EOF。因为ReadAll函数定义为从src读取直到EOF,所以它不会将从Read中读取的EOF视为错误报告。
ReadAll Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("Go is a general-purpose language designed with systems programming in mind.")
b, err := io.ReadAll(r)
if err != nil {
log.Fatal(err)
}
fmt.Printf("%s", b)
}
Output:
Go is a general-purpose language designed with systems programming in mind.
|
func ReadAtLeast
1
| func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)
|
ReadAtLeast函数从r中读取到buf,直到它读取至少min个字节。它返回已复制的字节数和错误(如果读取的字节数少于min个)。如果没有读取任何字节,则错误为EOF。如果在读取少于min个字节后出现EOF,则ReadAtLeast返回ErrUnexpectedEOF。如果min大于buf的长度,则ReadAtLeast返回ErrShortBuffer。返回时,当且仅当err == nil时,n >= min。如果r在读取至少min个字节后返回错误,则将删除该错误。
ReadAtLeast Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
| package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
buf := make([]byte, 14)
if _, err := io.ReadAtLeast(r, buf, 4); err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", buf)
// buffer smaller than minimal read size.
shortBuf := make([]byte, 3)
if _, err := io.ReadAtLeast(r, shortBuf, 4); err != nil {
fmt.Println("error:", err)
}
// minimal read size bigger than io.Reader stream
longBuf := make([]byte, 64)
if _, err := io.ReadAtLeast(r, longBuf, 64); err != nil {
fmt.Println("error:", err)
}
}
Output:
some io.Reader
error: short buffer
error: unexpected EOF
|
func ReadFull
1
| func ReadFull(r Reader, buf []byte) (n int, err error)
|
ReadFull函数从r中精确地读取len(buf)个字节到buf中。它返回已复制的字节数和错误(如果读取的字节数少于len(buf)个)。如果没有读取任何字节,则错误为EOF。如果在读取一些但不是所有字节后出现EOF,则ReadFull函数返回ErrUnexpectedEOF。返回时,当且仅当err == nil时,n == len(buf)。如果r在读取至少len(buf)个字节后返回错误,则将删除该错误。
ReadFull Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
| package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
buf := make([]byte, 4)
if _, err := io.ReadFull(r, buf); err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", buf)
// minimal read size bigger than io.Reader stream
longBuf := make([]byte, 64)
if _, err := io.ReadFull(r, longBuf); err != nil {
fmt.Println("error:", err)
}
}
Output:
some
error: unexpected EOF
|
func WriteString
1
| func WriteString(w Writer, s string) (n int, err error)
|
WriteString函数将字符串s的内容写入接受字节片的w中。如果w实现了StringWriter,则直接调用其WriteString方法。否则,将调用w.Write一次。
WriteString Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| package main
import (
"io"
"log"
"os"
)
func main() {
if _, err := io.WriteString(os.Stdout, "Hello World"); err != nil {
log.Fatal(err)
}
}
Output:
Hello World
|
类型
type ByteReader
1
2
3
| type ByteReader interface {
ReadByte() (byte, error)
}
|
ByteReader是封装了ReadByte方法的接口。
ReadByte读取并返回输入中的下一个字节或遇到的任何错误。如果ReadByte返回错误,则没有输入字节被消耗,返回的字节值未定义。
ReadByte提供了逐字节处理的有效接口。如果Reader未实现ByteReader,则可以使用bufio.NewReader进行封装以添加此方法。
type ByteScanner
1
2
3
4
| type ByteScanner interface {
ByteReader
UnreadByte() error
}
|
ByteScanner是在基本ReadByte方法上添加了UnreadByte方法的接口。
UnreadByte方法使得下一次调用ReadByte方法返回上次读取的最后一个字节。如果上次操作不是对ReadByte方法的成功调用,则UnreadByte方法可能会返回错误,未读取最后一个字节(或上一个未读取字节),或(在支持Seeker接口的实现中)将偏移量设置为当前偏移量前一个字节。
type ByteWriter <- go1.1
1
2
3
| type ByteWriter interface {
WriteByte(c byte) error
}
|
ByteWriter是封装了WriteByte方法的接口。
type Closer
1
2
3
| type Closer interface {
Close() error
}
|
Closer是封装了基本Close方法的接口。
第一次调用Close方法后的行为是未定义的。具体的实现可能会记录自己的行为。
type LimitedReader
1
2
3
4
| type LimitedReader struct {
R Reader // 底层的 Reader
N int64 // 最多可以读取的字节数
}
|
LimitedReader结构体从 R 中读取数据,但是限制了返回数据的数量,只有最多 N 个字节。每次调用 Read 都会更新 N 的值以反映新的剩余字节数。当 N <= 0 或者底层的 R 返回 EOF 时,Read 会返回 EOF。
(*LimitedReader) Read
1
| func (l *LimitedReader) Read(p []byte) (n int, err error)
|
type OffsetWriter <- go1.20
1
2
3
4
| type OffsetWriter struct {
// contains filtered or unexported fields
// 包含已过滤或未导出的字段
}
|
OffsetWriter结构体将写入基于 offset 的数据映射到底层 Writer 中基于 base+off 的偏移位置。
func NewOffsetWriter <- go1.20
1
| func NewOffsetWriter(w WriterAt, off int64) *OffsetWriter
|
NewOffsetWriter函数返回一个 OffsetWriter,它从 offset 位置开始写入 w。
(*OffsetWriter) Seek <- go1.20
1
| func (o *OffsetWriter) Seek(offset int64, whence int) (int64, error)
|
(*OffsetWriter) Write <- go1.20
1
| func (o *OffsetWriter) Write(p []byte) (n int, err error)
|
(*OffsetWriter) WriteAt <- go1.20
1
| func (o *OffsetWriter) WriteAt(p []byte, off int64) (n int, err error)
|
type PipeReader
1
2
3
4
| type PipeReader struct {
// contains filtered or unexported fields
// 包含已过滤或未导出的字段
}
|
PipeReader结构体是管道的读取端。
(*PipeReader) Close
1
| func (r *PipeReader) Close() error
|
Close方法关闭读取器;后续对管道写入端的写入将返回 ErrClosedPipe 错误。
(*PipeReader) CloseWithError
1
| func (r *PipeReader) CloseWithError(err error) error
|
CloseWithError方法关闭读取器;后续对管道写入端的写入将返回 err 错误。
如果存在先前的错误,CloseWithError不会覆盖它并始终返回nil。
(*PipeReader) Read
1
| func (r *PipeReader) Read(data []byte) (n int, err error)
|
Read方法实现标准的Read接口:它从管道中读取数据,在写入方到达或写入端关闭之前阻塞。如果写入端以错误关闭,则将该错误作为err返回;否则err为EOF。
type PipeWriter
1
2
3
4
| type PipeWriter struct {
// contains filtered or unexported fields
// 包含已过滤或未导出的字段
}
|
PipeWriter结构体是管道的写入方。
(*PipeWriter) Close
1
| func (w *PipeWriter) Close() error
|
Close关闭写入器;随后从读取器读取数据将不会返回字节和EOF。
(*PipeWriter) CloseWithError
1
| func (w *PipeWriter) CloseWithError(err error) error
|
CloseWithError方法关闭写入器;随后从读取器读取数据将不会返回字节和错误err,如果err为nil,则返回EOF。
如果存在先前的错误,CloseWithError不会覆盖它并始终返回nil。
(*PipeWriter) Write
1
| func (w *PipeWriter) Write(data []byte) (n int, err error)
|
Write方法实现标准的Write接口:它将数据写入管道,阻塞直到一个或多个读取器消耗了所有数据或读取端关闭。如果读取端以错误关闭,则将该err返回;否则err为ErrClosedPipe。
type ReadCloser
1
2
3
4
| type ReadCloser interface {
Reader
Closer
}
|
ReadCloser接口组合了基本的Read和Close方法。
func NopCloser <- go1.16
1
| func NopCloser(r Reader) ReadCloser
|
NopCloser函数返回一个带有no-op Close方法的ReadCloser,封装提供的Reader r。如果r实现了WriterTo,则返回的ReadCloser将通过转发调用来实现WriterTo方法。
type ReadSeekCloser <- go1.16
1
2
3
4
5
| type ReadSeekCloser interface {
Reader
Seeker
Closer
}
|
ReadSeekCloser接口组合了基本的Read、Seek和Close方法。
type ReadSeeker
1
2
3
4
| type ReadSeeker interface {
Reader
Seeker
}
|
ReadSeeker接口组合了基本的Read、Seek方法。
type ReadWriteCloser
1
2
3
4
5
| type ReadWriteCloser interface {
Reader
Writer
Closer
}
|
ReadWriteCloser接口组合了基本的Read、Write和Close方法。
type ReadWriteSeeker
1
2
3
4
5
| type ReadWriteSeeker interface {
Reader
Writer
Seeker
}
|
ReadWriteSeeker接口组合了基本的Read、Write和Seek方法。
type ReadWriter
1
2
3
4
| type ReadWriter interface {
Reader
Writer
}
|
ReadWriter接口组合了基本的Read和Write方法。
type Reader
1
2
3
| type Reader interface {
Read(p []byte) (n int, err error)
}
|
Reader接口封装了基本的Read方法。
Read方法将最多len(p)个字节读取到p中。它返回读取的字节数(0 <= n <= len(p))以及任何遇到的错误。即使Read返回n < len(p),它也可以在调用期间使用p作为临时空间。如果一些数据可用但不足len(p)字节,则Read通常返回可用的内容而不是等待更多。
当Read方法在成功读取n > 0个字节后遇到错误或文件结束条件时,它返回读取的字节数。它可能从同一调用返回(非零)错误,也可能从后续调用返回错误(n == 0)。一般情况下,一个返回非零字节数并在输入流结束时返回EOF或nil错误的Reader实例,下一次Read应该返回0,EOF。
在考虑错误err之前,调用者应始终处理返回的n > 0字节。这样做可以正确处理在读取一些字节之后发生的I/O错误,以及两种允许的EOF行为。
实现Read的方法不应该返回具有nil错误的零字节计数,除非len(p) == 0。调用者应该将返回0和nil视为表示没有发生任何事情;特别是它不表示EOF。
实现不能保留p。
func LimitReader
1
| func LimitReader(r Reader, n int64) Reader
|
LimitReader函数返回一个从 r 读取但在读取 n 个字节后停止并返回 EOF 的 Reader。底层实现是一个 *LimitedReader。
LimitReader Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
lr := io.LimitReader(r, 4)
if _, err := io.Copy(os.Stdout, lr); err != nil {
log.Fatal(err)
}
}
Output:
some
|
func MultiReader
1
| func MultiReader(readers ...Reader) Reader
|
MultiReader函数返回一个 Reader,它是提供的输入 readers 的逻辑连接。它们按顺序读取。一旦所有输入都返回 EOF,Read 将返回 EOF。如果任何读取器返回非 nil、非 EOF 错误,则 Read 将返回该错误。
MultiReaderExample
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r1 := strings.NewReader("first reader ")
r2 := strings.NewReader("second reader ")
r3 := strings.NewReader("third reader\n")
r := io.MultiReader(r1, r2, r3)
if _, err := io.Copy(os.Stdout, r); err != nil {
log.Fatal(err)
}
}
Output:
first reader second reader third reader
|
func TeeReader
1
| func TeeReader(r Reader, w Writer) Reader
|
TeeReader函数返回一个 Reader,它从 r 中读取并将其写入 w。通过它执行的所有对 r 的读取都将与对 w 的相应写入匹配。没有内部缓冲区——写入必须在读取完成之前完成。任何在写入时遇到的错误都将作为读取错误报告。
TeeReader Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
var r io.Reader = strings.NewReader("some io.Reader stream to be read\n")
r = io.TeeReader(r, os.Stdout)
// Everything read from r will be copied to stdout.
if _, err := io.ReadAll(r); err != nil {
log.Fatal(err)
}
}
Output:
some io.Reader stream to be read
|
type ReaderAt
1
2
3
| type ReaderAt interface {
ReadAt(p []byte, off int64) (n int, err error)
}
|
ReaderAt 是封装基本 ReadAt 方法的接口。
ReadAt方法从基础输入源的偏移量 off 开始将 len(p) 个字节读入 p 中。它返回读取的字节数(0 <= n <= len(p))和任何遇到的错误。
当 ReadAt方法返回 n < len(p) 时,它返回一个非 nil 的错误,解释为什么没有返回更多的字节。在这方面,ReadAt方法比 Read方法更严格。
即使 ReadAt方法返回 n < len(p),它也可以在调用期间使用 p 中的所有字节作为临时空间。如果有一些数据可用但不是 len(p) 字节,则 ReadAt 阻塞,直到所有数据都可用或发生错误。在这方面,ReadAt 不同于 Read。
如果 ReadAt方法返回的 n = len(p) 字节在输入源的末尾,则 ReadAt 可能返回 err == EOF 或 err == nil。
如果 ReadAt方法从具有 seek 偏移量的输入源中读取,则 ReadAt方法不应影响底层 seek 偏移量,也不应受其影响。
ReadAt方法的客户端可以在同一输入源上并行执行 ReadAt方法调用。
实现不得保留 p。
type ReaderFrom
1
2
3
| type ReaderFrom interface {
ReadFrom(r Reader) (n int64, err error)
}
|
ReaderFrom 是封装 ReadFrom 方法的接口。
ReadFrom方法从 r 中读取数据,直到 EOF 或错误。返回值 n 是读取的字节数。除了 EOF 之外,在读取过程中遇到的任何错误也将返回。
如果可用,Copy函数将使用 ReaderFrom方法。
type RuneReader
1
2
3
| type RuneReader interface {
ReadRune() (r rune, size int, err error)
}
|
RuneReader 是封装了 ReadRune 方法的接口。
ReadRune方法读取一个单一的编码的 Unicode 字符并返回该字符以及其所占用的字节数。如果没有字符可用,则 err 将被设置。
type RuneScanner
1
2
3
4
| type RuneScanner interface {
RuneReader
UnreadRune() error
}
|
RuneScanner 是在基本 ReadRune 方法上添加了 UnreadRune 方法的接口。
UnreadRune方法会导致下一次调用 ReadRune方法返回上次读取的最后一个字符。如果上次操作不是成功的 ReadRune方法调用,则 UnreadRune方法可能会返回错误、未读取最后一个字符(或最后一个未读取字符之前的字符),或者(在支持 Seeker 接口的实现中)定位到当前偏移量之前的字符的开头。
type SectionReader
1
2
3
4
| type SectionReader struct {
// contains filtered or unexported fields
// 包含已过滤或未导出的字段
}
|
SectionReader 在底层的 ReaderAt方法的一部分实现了 Read、Seek 和 ReadAt方法。
SectionReader Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
s := io.NewSectionReader(r, 5, 17)
if _, err := io.Copy(os.Stdout, s); err != nil {
log.Fatal(err)
}
}
Output:
io.Reader stream
|
func NewSectionReader
1
| func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader
|
NewSectionReader函数返回一个 SectionReader,该 Reader 从偏移量 off 处开始从 r 读取并在 n 字节后以 EOF 结束。
(*SectionReader) Read
1
| func (s *SectionReader) Read(p []byte) (n int, err error)
|
Read Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
s := io.NewSectionReader(r, 5, 17)
buf := make([]byte, 9)
if _, err := s.Read(buf); err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", buf)
}
Output:
io.Reader
|
(*SectionReader) ReadAt
1
| func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error)
|
ReadAt Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
| package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
s := io.NewSectionReader(r, 5, 17)
buf := make([]byte, 6)
if _, err := s.ReadAt(buf, 10); err != nil {
log.Fatal(err)
}
fmt.Printf("%s\n", buf)
}
Output:
stream
|
(*SectionReader) Seek
1
| func (s *SectionReader) Seek(offset int64, whence int) (int64, error)
|
Seek Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
| package main
import (
"io"
"log"
"os"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
s := io.NewSectionReader(r, 5, 17)
if _, err := s.Seek(10, io.SeekStart); err != nil {
log.Fatal(err)
}
if _, err := io.Copy(os.Stdout, s); err != nil {
log.Fatal(err)
}
}
Output:
stream
|
(*SectionReader) Size
1
| func (s *SectionReader) Size() int64
|
Size方法返回该 SectionReader 中字节的大小。
Size Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| package main
import (
"fmt"
"io"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
s := io.NewSectionReader(r, 5, 17)
fmt.Println(s.Size())
}
Output:
17
|
type Seeker
1
2
3
| type Seeker interface {
Seek(offset int64, whence int) (int64, error)
}
|
Seeker 是封装基本 Seek 方法的接口。
Seek方法设置下一个 Read 或 Write 的偏移量,根据 whence 进行解释:SeekStart 表示相对于文件的开头,SeekCurrent 表示相对于当前偏移量,SeekEnd 表示相对于结尾(例如,offset = -2 表示文件的倒数第二个字节)。Seek 返回相对于文件开头的新偏移量,或者如果有的话,返回错误。
寻找到文件开头之前的偏移量是一个错误。寻找任何正偏移量可能是允许的,但是如果新的偏移量超过底层对象的大小,则随后的 I/O 操作的行为取决于实现。
type StringWriter <- go1.12
1
2
3
| type StringWriter interface {
WriteString(s string) (n int, err error)
}
|
StringWriter 是封装 WriteString 方法的接口。
type WriteCloser
1
2
3
4
| type WriteCloser interface {
Writer
Closer
}
|
WriteCloser 是组合基本的 Write 和 Close 方法的接口。
type WriteSeeker
1
2
3
4
| type WriteSeeker interface {
Writer
Seeker
}
|
WriteSeeker 是组合基本的 Write 和 Seek 方法的接口。
type Writer
1
2
3
| type Writer interface {
Write(p []byte) (n int, err error)
}
|
Writer 是封装基本 Write 方法的接口。
Write方法从 p 中写入 len(p) 个字节到基础数据流中。它返回从 p 中写入的字节数 n(0 <= n <= len(p))和任何导致写入提前停止的错误。如果它返回 n < len(p),则 Write 必须返回非 nil 错误。Write 必须不修改切片数据,即使是暂时的也不行。
实现不得保留p。
1
| var Discard Writer = discard{}
|
Discard 是一个 Writer,所有的写入调用都会成功地且不进行任何操作。
func MultiWriter
1
| func MultiWriter(writers ...Writer) Writer
|
MultiWriter函数创建一个将其写入复制到所有提供的 writer 的 writer,类似于 Unix 的 tee(1) 命令。
每个写入都写入到每个列出的 writer 中,一个接一个地。如果列出的 writer 返回错误,整个写操作将停止并返回该错误;不会继续下一个 writer。
MultiWriter Example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
| package main
import (
"fmt"
"io"
"log"
"strings"
)
func main() {
r := strings.NewReader("some io.Reader stream to be read\n")
var buf1, buf2 strings.Builder
w := io.MultiWriter(&buf1, &buf2)
if _, err := io.Copy(w, r); err != nil {
log.Fatal(err)
}
fmt.Print(buf1.String())
fmt.Print(buf2.String())
}
Output:
some io.Reader stream to be read
some io.Reader stream to be read
|
type WriterAt
1
2
3
| type WriterAt interface {
WriteAt(p []byte, off int64) (n int, err error)
}
|
WriterAt 是封装 WriteAt 方法的接口。
WriteAt方法从偏移量off处将长度为len(p)的p写入底层数据流。它返回写入的字节数(0 <= n <= len(p))和任何导致写入提前停止的错误。如果返回n < len(p),WriteAt必须返回非nil的错误。
如果WriteAt方法正在向带有寻址偏移量的目标写入,则WriteAt方法不应受到影响,也不应影响基础寻址偏移量。
如果WriteAt方法正在向目标写入数据,则客户端可以在同一目标上并行执行WriteAt方法调用,前提是范围不重叠。
实现不得保留p。
type WriterTo
1
2
3
| type WriterTo interface {
WriteTo(w Writer) (n int64, err error)
}
|
WriterTo是封装WriteTo方法的接口。
WriteTo方法写入数据直到没有更多数据可写或出现错误。返回值n是写入的字节数。任何在写入期间遇到的错误也将返回。
如果可用,Copy函数将使用WriterTo方法。