package io

import "io"

io 包提供I/O原语的基础接口。 其主要作用是将此类原语的现有实现(如os包中的实现) 封装为抽象功能的共享公共接口,并附带一些其他相关原语。

由于这些接口和原语封装了具有不同实现的底层操作, 除非另有说明,调用方不应假定它们可安全用于并行执行。

Index

Examples

Constants

const (
	SeekStart   = 0 // 相对于文件起始位置进行偏移
	SeekCurrent = 1 // 相对于当前偏移位置进行偏移
	SeekEnd     = 2 // 相对于文件末尾进行偏移
)

Seek 起始基准值。

Variables

var EOF = errors.New("EOF")

EOF 是Read方法在无更多输入数据时返回的错误。 (Read必须直接返回EOF本身,而非包装EOF的错误, 因为调用方会通过==判断EOF。) 函数仅应在输入正常结束时返回EOF。 若在结构化数据流中意外遇到EOF, 应返回[ErrUnexpectedEOF]或其他能提供更多细节的错误。

var ErrClosedPipe = errors.New("io: read/write on closed pipe")

ErrClosedPipe 是对已关闭管道执行读或写操作时返回的错误。

var ErrNoProgress = errors.New("multiple Read calls return no data or error")

ErrNoProgress 由部分[Reader]调用方返回, 当多次调用Read均未返回任何数据或错误时触发, 通常表明[Reader]的实现存在问题。

var ErrShortBuffer = errors.New("short buffer")

ErrShortBuffer 表示读取操作需要的缓冲区长度大于提供的长度。

var ErrShortWrite = errors.New("short write")

ErrShortWrite 表示写入操作接收的字节数少于请求数量, 但未返回显式错误。

var ErrUnexpectedEOF = errors.New("unexpected EOF")

ErrUnexpectedEOF 表示在读取固定大小的数据块或数据结构的过程中 遇到了EOF。

Functions

func Copy

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)实现复制。

Example
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

func CopyBuffer(dst Writer, src Reader, buf []byte) (written int64, err error)

CopyBuffer 与Copy功能相同,区别在于它通过提供的缓冲区(若需要) 中转数据,而非分配临时缓冲区。若buf为nil,则自动分配缓冲区; 若buf长度为0,CopyBuffer会触发panic。

若src实现[WriterTo]或dst实现[ReaderFrom], 则不会使用buf执行复制。

Example
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

func CopyN(dst Writer, src Reader, n int64) (written int64, err error)

CopyN 从src向dst复制n个字节(或直至发生错误)。 它返回复制的字节数,以及复制过程中遇到的首个错误。 返回时,当且仅当err == nil时,written == n。

若dst实现[ReaderFrom],则通过该接口实现复制。

Example
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

func Pipe() (*PipeReader, *PipeWriter)

Pipe 创建一个同步的内存管道。 它可用于将期望 io.Reader 的代码与期望 io.Writer 的代码连接起来。

管道上的读操作与写操作一一对应,除非需要多次读操作才能消费完一次写入的数据。 也就是说,对 PipeWriter 的每次写入都会阻塞,直到 PipeReader 的一次或多次读操作 完全消费完写入的数据。 数据从写入操作直接复制到对应的读操作(或多次读操作)中,无内部缓冲。

并行调用 Read、Write 或 Close 是安全的。 并行调用多次 Read、并行调用多次 Write 同样安全: 各个调用会被串行化执行。

Example
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

func ReadAll(r Reader) ([]byte, error)

ReadAll 从r中读取数据直至发生错误或EOF, 并返回读取到的数据。 成功调用会返回err == nil,而非err == EOF。 由于ReadAll的定义是从源读取至EOF, 因此不会将Read返回的EOF视为需要上报的错误。

Example
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

func ReadAtLeast(r Reader, buf []byte, min int) (n int, err error)

ReadAtLeast 从r中读取数据至buf,直至至少读取min个字节。 它返回复制的字节数,若读取字节数不足则返回错误。 仅当未读取任何字节时,错误才为EOF。 若在读取不足min个字节后遇到EOF, ReadAtLeast返回[ErrUnexpectedEOF]。 若min大于buf的长度,ReadAtLeast返回[ErrShortBuffer]。 返回时,当且仅当err == nil时,n >= min。 若r在至少读取min个字节后返回错误,该错误会被忽略。

Example
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

func ReadFull(r Reader, buf []byte) (n int, err error)

ReadFull 从r中精确读取len(buf)个字节至buf。 它返回复制的字节数,若读取字节数不足则返回错误。 仅当未读取任何字节时,错误才为EOF。 若在读取部分但非全部字节后遇到EOF, ReadFull返回[ErrUnexpectedEOF]。 返回时,当且仅当err == nil时,n == len(buf)。 若r在至少读取len(buf)个字节后返回错误,该错误会被忽略。

Example
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

func WriteString(w Writer, s string) (n int, err error)

WriteString 将字符串s的内容写入w,w为接收字节切片的写入器。 若w实现[StringWriter],则直接调用[StringWriter.WriteString]。 否则,仅调用一次[Writer.Write]。

Example
package main

import (
	"io"
	"log"
	"os"
)

func main() {
	if _, err := io.WriteString(os.Stdout, "Hello World"); err != nil {
		log.Fatal(err)
	}

}

Output:

Hello World

Types

type ByteReader

type ByteReader interface {
	ReadByte() (byte, error)
}

ByteReader 是封装ReadByte方法的接口。

ReadByte 从输入中读取并返回下一个字节, 或返回遇到的任何错误。若ReadByte返回错误, 则未消耗任何输入字节,返回的字节值未定义。

ReadByte 为逐字节处理提供了高效接口。 未实现ByteReader的[Reader]可通过bufio.NewReader包装 以添加该方法。

type ByteScanner

type ByteScanner interface {
	ByteReader
	UnreadByte() error
}

ByteScanner 是在基础ReadByte方法基础上 新增UnreadByte方法的接口。

UnreadByte 会使下一次ReadByte调用返回最后读取的字节。 若上一次操作并非成功的ReadByte调用,UnreadByte可能 返回错误、回退最后读取的字节(或上一次回退字节的前一个字节), 或(在支持[Seeker]接口的实现中)将偏移量定位至当前位置的前一个字节。

type ByteWriter

type ByteWriter interface {
	WriteByte(c byte) error
}

ByteWriter 是封装WriteByte方法的接口。

type Closer

type Closer interface {
	Close() error
}

Closer 是封装基础Close方法的接口。

首次调用Close后的行为未定义。 具体实现可自行文档化其行为。

type LimitedReader

type LimitedReader struct {
	R Reader // 底层读取器
	N int64  // 剩余最大可读字节数
}

LimitedReader 从R中读取数据,但将返回的数据量限制为N个字节。 每次调用Read都会更新N以反映剩余的可读数据量。 当N <= 0或底层R返回EOF时,Read返回EOF。

func (*LimitedReader) Read

func (l *LimitedReader) Read(p []byte) (n int, err error)

type OffsetWriter

type OffsetWriter struct {
	// contains filtered or unexported fields
}

OffsetWriter 将在base偏移量处的写入操作, 映射到底层写入器的base+off偏移量处。

func NewOffsetWriter

func NewOffsetWriter(w WriterAt, off int64) *OffsetWriter

NewOffsetWriter 返回一个[OffsetWriter], 该写入器从off偏移位置开始向w中写入数据。

func (*OffsetWriter) Seek

func (o *OffsetWriter) Seek(offset int64, whence int) (int64, error)

func (*OffsetWriter) Write

func (o *OffsetWriter) Write(p []byte) (n int, err error)

func (*OffsetWriter) WriteAt

func (o *OffsetWriter) WriteAt(p []byte, off int64) (n int, err error)

type PipeReader

type PipeReader struct {
	// contains filtered or unexported fields
}

PipeReader 是管道的读取端。

func (*PipeReader) Close

func (r *PipeReader) Close() error

Close 关闭读取端;后续对管道写入端的写入操作将返回 ErrClosedPipe 错误。

func (*PipeReader) CloseWithError

func (r *PipeReader) CloseWithError(err error) error

CloseWithError 关闭读取端;后续对管道写入端的写入操作将返回 err 错误。

若已存在错误,CloseWithError 不会覆盖原有错误,且始终返回 nil。

func (*PipeReader) Read

func (r *PipeReader) Read(data []byte) (n int, err error)

Read 实现标准的 Read 接口: 它从管道中读取数据,会阻塞直到写入方写入数据或写入端关闭。 若写入端因错误关闭,该错误会作为 err 返回;否则 err 为 EOF。

type PipeWriter

type PipeWriter struct {
	// contains filtered or unexported fields
}

PipeWriter 是管道的写入端。

func (*PipeWriter) Close

func (w *PipeWriter) Close() error

Close 关闭写入端;后续从管道读取端的读取操作将返回0字节数据及EOF。

func (*PipeWriter) CloseWithError

func (w *PipeWriter) CloseWithError(err error) error

CloseWithError 关闭写入端;后续从管道读取端的读取操作将返回0字节数据及err错误, 若err为nil则返回EOF。

若已存在错误,CloseWithError 不会覆盖原有错误,且始终返回 nil。

func (*PipeWriter) Write

func (w *PipeWriter) Write(data []byte) (n int, err error)

Write 实现标准的 Write 接口: 它向管道写入数据,会阻塞直到一个或多个读取方消费完所有数据,或读取端关闭。 若读取端因错误关闭,该错误会作为 err 返回;否则 err 为 ErrClosedPipe。

type ReadCloser

type ReadCloser interface {
	Reader
	Closer
}

ReadCloser 是组合基础Read和Close方法的接口。

func NopCloser

func NopCloser(r Reader) ReadCloser

NopCloser 返回一个包装了提供的[Reader] r的[ReadCloser], 其Close方法为空操作。 若r实现[WriterTo],返回的[ReadCloser]会通过转发调用至r 来实现[WriterTo]接口。

type ReadSeekCloser

type ReadSeekCloser interface {
	Reader
	Seeker
	Closer
}

ReadSeekCloser 是组合基础Read、Seek和Close方法的接口。

type ReadSeeker

type ReadSeeker interface {
	Reader
	Seeker
}

ReadSeeker 是组合基础Read和Seek方法的接口。

type ReadWriteCloser

type ReadWriteCloser interface {
	Reader
	Writer
	Closer
}

ReadWriteCloser 是组合基础Read、Write和Close方法的接口。

type ReadWriteSeeker

type ReadWriteSeeker interface {
	Reader
	Writer
	Seeker
}

ReadWriteSeeker 是组合基础Read、Write和Seek方法的接口。

type ReadWriter

type ReadWriter interface {
	Reader
	Writer
}

ReadWriter 是组合基础Read和Write方法的接口。

type Reader

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个字节后遇到错误或文件结束条件时, 会返回已读取的字节数。它可在本次调用中返回(非nil)错误, 或在后续调用中返回错误(且n == 0)。 此类常见场景的一个例子是:在输入流末尾返回非零字节数的Reader, 可能返回err == EOF或err == nil。下一次Read应返回0, EOF。

调用方应始终先处理返回的n > 0个字节,再考虑错误err。 这样能正确处理读取部分字节后发生的I/O错误, 以及两种允许的EOF行为。

若len(p) == 0,Read应始终返回n == 0。若已知存在错误条件(如EOF), 可返回非nil错误。

不鼓励Read的实现返回零字节计数且nil错误,len(p) == 0的情况除外。 调用方应将返回0和nil视为无任何操作发生; 尤其该情况不表示EOF。

实现不得持有p的引用。

func LimitReader

func LimitReader(r Reader, n int64) Reader

LimitReader 返回一个Reader,该读取器从r中读取数据, 但在读取n个字节后以EOF终止。 底层实现为*LimitedReader。

Example
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

func MultiReader(readers ...Reader) Reader

MultiReader 返回一个读取器,该读取器是所提供输入读取器的逻辑拼接 会按顺序读取这些输入读取器。一旦所有输入都返回 EOF,Read 方法将返回 EOF 若任意一个读取器返回非空、非 EOF 的错误,Read 方法将返回该错误

Example
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

func TeeReader(r Reader, w Writer) Reader

TeeReader 返回一个[Reader],该读取器会将从r中读取的内容 同时写入w。 通过该读取器从r执行的所有读取操作, 都会对应执行向w的写入操作。无内部缓冲—— 写入必须在读取完成前执行完毕。 写入过程中遇到的任何错误都会作为读取错误上报。

Example
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

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从带有偏移量的输入源读取, ReadAt不应影响底层偏移量,也不受其影响。

ReadAt的调用方可对同一输入源并行执行多个ReadAt调用。

实现不得持有p的引用。

type ReaderFrom

type ReaderFrom interface {
	ReadFrom(r Reader) (n int64, err error)
}

ReaderFrom 是封装ReadFrom方法的接口。

ReadFrom 从r中读取数据直至EOF或发生错误。 返回值n为读取的字节数。 读取过程中遇到的除EOF外的任何错误也会一并返回。

若可用,[Copy]函数会使用[ReaderFrom]。

type RuneReader

type RuneReader interface {
	ReadRune() (r rune, size int, err error)
}

RuneReader 是封装ReadRune方法的接口。

ReadRune 读取单个编码的Unicode字符, 并返回该符文及其字节长度。若无可用字符,会设置err。

type RuneScanner

type RuneScanner interface {
	RuneReader
	UnreadRune() error
}

RuneScanner 是在基础ReadRune方法基础上 新增UnreadRune方法的接口。

UnreadRune 会使下一次ReadRune调用返回最后读取的符文。 若上一次操作并非成功的ReadRune调用,UnreadRune可能 返回错误、回退最后读取的符文(或上一次回退符文的前一个符文), 或(在支持[Seeker]接口的实现中)将偏移量定位至当前符文的起始位置。

type SectionReader

type SectionReader struct {
	// contains filtered or unexported fields
}

SectionReader 在底层[ReaderAt]的指定片段上 实现Read、Seek和ReadAt方法。

Example
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

func NewSectionReader(r ReaderAt, off int64, n int64) *SectionReader

NewSectionReader 返回一个[SectionReader], 该读取器从r的off偏移位置开始读取, 读取n个字节后以EOF终止。

func (*SectionReader) Outer

func (s *SectionReader) Outer() (r ReaderAt, off int64, n int64)

Outer 返回该片段对应的底层[ReaderAt]与偏移量。

返回值与创建[SectionReader]时 传入[NewSectionReader]的参数一致。

func (*SectionReader) Read

func (s *SectionReader) Read(p []byte) (n int, err error)
Example
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

func (*SectionReader) ReadAt

func (s *SectionReader) ReadAt(p []byte, off int64) (n int, err error)
Example
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

func (*SectionReader) Seek

func (s *SectionReader) Seek(offset int64, whence int) (int64, error)
Example
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

func (*SectionReader) Size

func (s *SectionReader) Size() int64

Size 返回该片段的字节大小。

Example
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

type Seeker interface {
	Seek(offset int64, whence int) (int64, error)
}

Seeker 是封装基础Seek方法的接口。

Seek 将下一次Read或Write的偏移量设置为offset, 偏移规则由whence指定: SeekStart 表示相对于文件起始位置, SeekCurrent 表示相对于当前偏移位置, SeekEnd 表示相对于文件末尾 (例如,offset = -2 指定文件的倒数第二个字节)。 Seek 返回相对于文件起始位置的新偏移量,或发生的错误。

偏移至文件起始位置之前属于错误操作。 允许偏移至任意正偏移量,但若新偏移量超过 底层对象的大小,后续I/O操作的行为由具体实现决定。

type StringWriter

type StringWriter interface {
	WriteString(s string) (n int, err error)
}

StringWriter 是封装WriteString方法的接口。

type WriteCloser

type WriteCloser interface {
	Writer
	Closer
}

WriteCloser 是组合基础Write和Close方法的接口。

type WriteSeeker

type WriteSeeker interface {
	Writer
	Seeker
}

WriteSeeker 是组合基础Write和Seek方法的接口。

type Writer

type Writer interface {
	Write(p []byte) (n int, err error)
}

Writer 是封装基础Write方法的接口。

Write 从p中将len(p)个字节写入底层数据流。 它返回从p中写入的字节数(0 <= n <= len(p)) 以及导致写入提前终止的任何错误。 若Write返回n < len(p),则必须返回非nil错误。 Write不得修改切片数据,即使是临时修改也不允许。

实现不得持有p的引用。

var Discard Writer = discard{}

Discard 是一个[Writer],所有对其的Write调用 均会成功执行且不做任何实际操作。

func MultiWriter

func MultiWriter(writers ...Writer) Writer

MultiWriter 创建一个写入器,该写入器会将写入操作复制到所有提供的写入器 类似于 Unix 的 tee(1) 命令

每次写入会依次写入列表中的每个写入器 若列表中的某个写入器返回错误,整个写入操作将停止并返回该错误 不会继续向后续写入器执行写入

Example
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

type WriterAt interface {
	WriteAt(p []byte, off int64) (n int, err error)
}

WriterAt 是封装基础WriteAt方法的接口。

WriteAt 从p中将len(p)个字节写入底层数据流的off偏移位置。 它返回从p中写入的字节数(0 <= n <= len(p)) 以及导致写入提前终止的任何错误。 若WriteAt返回n < len(p),则必须返回非nil错误。

若WriteAt向带有偏移量的目标写入, WriteAt不应影响底层偏移量,也不受其影响。

若写入范围不重叠,WriteAt的调用方可对同一目标 并行执行多个WriteAt调用。

实现不得持有p的引用。

type WriterTo

type WriterTo interface {
	WriteTo(w Writer) (n int64, err error)
}

WriterTo 是封装WriteTo方法的接口。

WriteTo 向w中写入数据,直至无更多数据可写或发生错误。 返回值n为写入的字节数。 写入过程中遇到的任何错误也会一并返回。

若可用,Copy函数会使用WriterTo。

Directories

fs fs 包定义了文件系统的基础接口。
ioutil ioutil 包实现了一些 I/O 工具函数。