Help us shape the future of Go! Take the 2026 Go Developer Survey

io_util

package module
v1.3.3 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Aug 15, 2026 License: MulanPSL-2.0 Imports: 13 Imported by: 1

README

一、说明

Go IO 操作工具库,提供并发安全的流转换、多路读写合并、内存管理、坐标轴标记等通用组件。

codecov Go Reference

二、安装

go get gitee.com/ivfzhou/io-util@latest

三、使用

3.1 WriteAt → Reader 管道转换

核心模式:创建一对写入端(WriteAtCloser,支持并发随机写入)和读取端(io.ReadCloser,顺序读出已写入数据)。写入端关闭后,读取端读完数据返回 io.EOF。写入端的错误会传递给读取端。

接口定义
type WriteAtCloser interface {
    io.WriterAt
    io.Closer
    CloseByError(error) error // 带错误关闭,error 会传递给 Reader
}

3.2 多路 ReadCloser 合并

NewMultiReadCloserToWriterAt — 多路并发写入 WriterAt

将多个 io.ReadCloser 的数据并发地以各自指定的偏移量写入同一个 io.WriterAt。

func NewMultiReadCloserToWriterAt(ctx context.Context, wa io.WriterAt) (
    send func(rc io.ReadCloser, offset int64) error,
    wait func(fastExit bool) error,
)
  • send — 提交一个 rc,数据将从 wa 的 offset 位置开始写入。所有 rc 在处理完毕后自动关闭。
  • wait — 调用后等待所有数据处理完毕。fastExit=true 表示遇错立即返回。
NewMultiReadCloserToWriter — 多路并发写入回调函数

将多个 io.ReadCloser 并发读取后通过回调写入目标位置。

func NewMultiReadCloserToWriter(ctx context.Context, writer func(offset int, p []byte)) (
    send func(readSize, offset int, reader io.ReadCloser),
    wait func() error,
)
  • send — 提交一个 reader,从中读取 readSize 字节写入 offset 位置。
  • wait — 等待全部读取完成。
NewMultiReadCloserToReader — 多路顺序合并为单一 Reader

将多个 io.ReadCloser 顺序合并为一个 io.Reader,读完一个自动切换到下一个。

func NewMultiReadCloserToReader(ctx context.Context, rc ...io.ReadCloser) (
    r io.Reader,
    add func(rc io.ReadCloser) error,
    endAdd func(),
)
  • r — 合并后的读取流。
  • add — 动态添加新的 rc。发生错误时停止添加,已添加的 rc 全部关闭。
  • endAdd — 声明不再添加新 rc,所有数据读完后 r 返回 io.EOF(务必调用)。

3.3 Reader → WriterAt 流式拷贝

func CopyReaderToWriterAt(r io.Reader, w io.WriterAt, offset int64, nonBuffer bool) (written int64, err error)

将 r 的数据流式写入 w 的指定偏移位置,直到 r 返回 io.EOF。nonBuffer=true 每次分配新内存;false 复用缓冲区并按需扩容。

Documentation

Index

Examples

Constants

View Source
const SegmentLength = 1024 * 4

SegmentLength 一个段占用的字节数。

Variables

View Source
var (
	ErrOffsetCannotNegative = errors.New("offset cannot negative")
	ErrWriterIsClosed       = errors.New("writer is closed")
	ErrReaderIsClosed       = errors.New("reader is closed")
)
View Source
var ErrAddAfterEnd = errors.New("add after end")

ErrAddAfterEnd 在 NewMultiReadCloserToReader 中,调用 endAdd 后再调用 add 将返回。

View Source
var ErrCallSendAfterWait = errors.New("call send after wait")

ErrCallSendAfterWait 在 NewMultiReadCloserToWriter 中,已经调用 wait 后再调用 send 将会返回。

Functions

func CopyFile deprecated

func CopyFile(src, dest string) error

CopyFile 复制文件。

Deprecated: 使用 os.Rename 代替。

func CopyReaderToWriterAt added in v1.0.2

func CopyReaderToWriterAt(r io.Reader, w io.WriterAt, offset int64, nonBuffer bool) (written int64, err error)

CopyReaderToWriterAt 将 r 中数据写入 w,直到 r 读取返回 io.EOF 结束读取。

r:要读取数据的流。

w:数据要写入的流。

offset:从 w 指定位置开始写入。

nonBuffer:读取数据时,每次都分配新的内存。

written:总计 w 写入数据的大小。

err:异常信息。

注意:offset 为负数将触发恐慌。

func NewMultiReadCloserToReader

func NewMultiReadCloserToReader(ctx context.Context, rc ...io.ReadCloser) (
	r io.Reader, add func(rc io.ReadCloser) error, endAdd func())

NewMultiReadCloserToReader 依次将 rc 中的数据转到 r 中读出。每一个 rc 读取数据直到 io.EOF 后调用关闭。

ctx:上下文。如果终止了,r 将返回 ctx.Err()。

rc:要读取数据的流。可以为空。

r:合并所有 rc 数据的流。

add:添加 rc,返回错误表明读取 rc 发生错误,将不再读取剩余的 rc,且所有添加进去的 rc 都会调用关闭。可以安全的添加空 rc。

endAdd:调用后表明不会再有 rc 添加,当所有 rc 数据读完了时,r 将返回 io.EOF。

注意:所有添加进去的 ReadCloser 都会被关闭,即使发生了错误。除非 r 没有读取直到 io.EOF。

注意:请务必调用 endAdd 以便 r 能读取完毕返回 io.EOF。

注意:在 endAdd 后再 add rc 将会触发恐慌返回 ErrAddAfterEnd,且该 rc 不会被关闭。

Example
package main

import (
	"context"
	"io"

	iu "gitee.com/ivfzhou/io-util"
)

func main() {
	ctx := context.Background()
	var rc1 io.ReadCloser
	var rc2 io.ReadCloser
	r, add, endAdd := iu.NewMultiReadCloserToReader(ctx, rc1, rc2)

	// 继续添加 Reader。
	go func() {
		var rc3 io.ReadCloser
		var rc4 io.ReadCloser
		err := add(rc3)
		err = add(rc4)
		_ = err
		// 处理 err。

		// 添加完所有 Reader 后调用。
		endAdd()
	}()

	// 将所有的 Reader 数据按顺序读出。
	bs, err := io.ReadAll(r)
	_, _ = bs, err
}

func NewMultiReadCloserToWriter

func NewMultiReadCloserToWriter(ctx context.Context, writer func(offset int, p []byte)) (
	send func(readSize, offset int, reader io.ReadCloser), wait func() error)

NewMultiReadCloserToWriter 依次从 reader 读出数据并写入 writer 中,并关闭 reader。

ctx:上下文,如果上下文终止了,将停止读取并返回 ctx.Err()。

writer:从 reader 中读取的数据将写入它。

send:提交 reader,读取 readSize 大小数据。如果读取不到足够的数据将返回错误。如果 reader 是空将触发恐慌。

wait:等待所有 reader 读取完毕。调用 wait 后不可再调用 send,否则触发恐慌。

func NewMultiReadCloserToWriterAt added in v1.0.2

func NewMultiReadCloserToWriterAt(ctx context.Context, wa io.WriterAt) (
	send func(rc io.ReadCloser, offset int64) error, wait func(fastExit bool) error)

NewMultiReadCloserToWriterAt 将 rc 数据读取并写入 wa。

ctx:上下文,如果终止了将终止流读写,并返回 ctx.Err()。

wa:从 rc 中读取的数据将写入它。

send:添加需要读取的数据流 rc。offset 表示从 wa 指定位置开始读取。所有 rc 都将关闭。若 rc 是空,将触发恐慌。

wait:添加完所有 rc 后调用,等待所有数据处理完毕。fastExit 表示当发生错误时,立刻返回该错误。

注意:若 wa 是空,将触发恐慌。

func NewWriteAtToReader2 added in v1.0.2

func NewWriteAtToReader2() (wc WriteAtCloser, rc ReadCloser)

NewWriteAtToReader2 同 NewWriteAtToReader 类似,但是 wc 会持有写入的字节,而不是复制一份。然后从 rc 处读出这些字节。

注意:对 wc 写入的字节变量的底层字节数组的修改,可能会影响到 rc 读取的字节也跟着被修改。因为它们是同一个底层字节数组。

Example
package main

import (
	"errors"

	iu "gitee.com/ivfzhou/io-util"
)

func main() {
	wc, rc := iu.NewWriteAtToReader2()

	// 读取完后关闭流。
	defer rc.Close()

	// 在另一个协程中写入数据。
	go func() {
		// 可并发写入。
		n, err := wc.WriteAt([]byte("hello world"), 0)

		// 处理 err 和 n。
		_, _ = n, err

		// 写入完毕后关闭流。
		wc.Close()

		// 如果处理过程中发生错误,可将错误信息传递给 rc。
		wc.CloseByError(errors.New("some error"))
	}()

	// 读取出 wc 中写入的数据。
	bs, err := iu.ReadAll(rc)

	// 处理 bs 和 err。
	_, _ = bs, err
}

func ReadAll added in v1.0.2

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

ReadAll 读取出所有字节,直到 r 返回 io.EOF。如果全部读出,没有错误,则 error 返回 nil,EOF 被剔除。

注意:如果 r 是空,将触发恐慌。

func ToReader added in v1.2.0

func ToReader(r ReadCloser) io.ReadCloser

ToReader 转换成 io.ReadCloser 对象。

func WrapError added in v1.0.2

func WrapError(err error) error

WrapError 包裹错误信息。

func WriteAtAll added in v1.2.0

func WriteAtAll(wa io.WriterAt, offset int64, p []byte) (written int64, err error)

WriteAtAll 将数据全部写入 wa。

Types

type AtomicError added in v1.0.2

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

AtomicError 原子性读取和设置错误信息。

func (*AtomicError) Get added in v1.0.2

func (e *AtomicError) Get() error

Get 获取内部错误信息。

func (*AtomicError) HasSet added in v1.0.2

func (e *AtomicError) HasSet() bool

HasSet 是否设置了错误信息。

func (*AtomicError) Set added in v1.0.2

func (e *AtomicError) Set(err error) bool

Set 设置错误信息,除非 err 是空。返回真表示设置成功。

type AxisMarker

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

AxisMarker 坐标轴标记器。

func (*AxisMarker) Get added in v1.0.1

func (m *AxisMarker) Get(offset, length int) int

Get 在坐标轴上,从 offset 开始向右获取被连续标记的长度,最大不超过 length。length 为负数表示向左标记。

offset:标记起点。

length:希望标记长度。

int:返回连续标记的长度。

注意:不可与 Mark 并发调用。

func (*AxisMarker) GetMaxMarkLine

func (m *AxisMarker) GetMaxMarkLine(begin int64) int64

GetMaxMarkLine 获取从某点开始连续被标记的长度。

func (*AxisMarker) Mark

func (m *AxisMarker) Mark(offset, length int)

Mark 标记坐标轴,从 offset 位置开始,往右数 length 长度的点。length 为负数表示向左标记点。

offset:标记起点。

length:标记长度。

注意;不可并发调用。

func (*AxisMarker) String

func (m *AxisMarker) String() string

String 返回坐标轴标记信息。

type Error added in v1.0.2

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

Error 错误对象。

func (*Error) Error added in v1.0.2

func (e *Error) Error() string

Error 接口实现。

func (*Error) String added in v1.0.2

func (e *Error) String() string

String 接口实现。

func (*Error) Unwrap added in v1.0.2

func (e *Error) Unwrap() error

Unwrap 接口实现。

type Queue

type Queue[E any] struct {
	// contains filtered or unexported fields
}

Queue 数据队列。

func (*Queue[E]) Close

func (q *Queue[E]) Close()

Close 从 GetFromChan 中获取的 chan 将被关闭。

func (*Queue[E]) GetFromChan

func (q *Queue[E]) GetFromChan() <-chan E

GetFromChan 获取队列头元素。

func (*Queue[E]) Push

func (q *Queue[E]) Push(elem E) bool

Push 向队列尾部加元素,如果队列关闭则不会加元素。

bool:添加成功返回 true。

type ReadCloser added in v1.0.2

type ReadCloser interface {
	Read() ([]byte, error)
	io.Closer
}

ReadCloser 数据读取接口。

type ReadCounter added in v1.3.0

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

func NewReadCounter added in v1.3.0

func NewReadCounter(reader io.Reader) *ReadCounter

NewReadCounter 读取字节计数器。获取 reader 被读出的字节数。调用 ReadCounter.Count 获取字节数。 reader 是 nil 将触发恐慌。

func (*ReadCounter) Count added in v1.3.0

func (r *ReadCounter) Count() int64

Count 获取被读出的字节数。

func (*ReadCounter) Read added in v1.3.0

func (r *ReadCounter) Read(p []byte) (n int, err error)

type Reader added in v1.0.2

type Reader interface {
	Read() ([]byte, error)
}

Reader 数据读取接口。

type SegmentManager added in v1.0.1

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

SegmentManager 多个段管理。

func (*SegmentManager) Discard added in v1.0.1

func (m *SegmentManager) Discard()

Discard 丢弃所有写入的数据,重置读取光标。

func (*SegmentManager) Read added in v1.0.1

func (m *SegmentManager) Read(bs []byte) (int, error)

Read 读取数据。

func (*SegmentManager) WriteAt added in v1.0.1

func (m *SegmentManager) WriteAt(bs []byte, offset int64) (int, error)

WriteAt 写入数据。

type WriteAtCloser

type WriteAtCloser interface {
	io.WriterAt
	io.Closer

	// CloseByError 关闭写入。
	//
	// error 将传递给 Reader 感知。
	CloseByError(error) error
}

WriteAtCloser 数据写入接口。

func NewWriteAtReader deprecated

func NewWriteAtReader() (wc WriteAtCloser, rc io.ReadCloser)

NewWriteAtReader 同 NewWriteAtToReader。

Deprecated: 使用 NewWriteAtToReader 代替。

func NewWriteAtToReader added in v1.0.1

func NewWriteAtToReader() (wc WriteAtCloser, rc io.ReadCloser)

NewWriteAtToReader 获取一个 WriteAtCloser 和 io.ReadCloser 对象,其中 wc 用于并发写入数据,与此同时 rc 读取出已经写入好的数据。

wc:写入流。字节临时写入到磁盘。写入完毕后关闭,则 rc 会全部读取完后返回 io.EOF。

rc:读取流。

wc 发生的错误会传递给 rc 返回。

Example
package main

import (
	"errors"
	"io"

	iu "gitee.com/ivfzhou/io-util"
)

func main() {
	wc, rc := iu.NewWriteAtToReader()

	// 读取完后关闭流。
	defer rc.Close()

	// 在另一个协程中写入数据。
	go func() {
		// 可并发写入。
		n, err := wc.WriteAt([]byte("hello world"), 0)

		// 处理 err 和 n。
		_, _ = n, err

		// 写入完毕后关闭流。
		wc.Close()

		// 如果处理过程中发生错误,可将错误信息传递给 rc。
		wc.CloseByError(errors.New("some error"))
	}()

	// 读取出 wc 中写入的数据。
	bs, err := io.ReadAll(rc)

	// 处理 bs 和 err。
	_, _ = bs, err
}

func NewWriteAtToReader3 added in v1.2.0

func NewWriteAtToReader3() (wc WriteAtCloser, rc io.ReadCloser)

NewWriteAtToReader3 同 NewWriteAtToReader 类似,但是 wc 写入的字节将放置在内存中。

Example
package main

import (
	"errors"
	"io"

	iu "gitee.com/ivfzhou/io-util"
)

func main() {
	wc, rc := iu.NewWriteAtToReader3()

	// 读取完后关闭流。
	defer rc.Close()

	// 在另一个协程中写入数据。
	go func() {
		// 可并发写入。
		n, err := wc.WriteAt([]byte("hello world"), 0)

		// 处理 err 和 n。
		_, _ = n, err

		// 写入完毕后关闭流。
		wc.Close()

		// 如果处理过程中发生错误,可将错误信息传递给 rc。
		wc.CloseByError(errors.New("some error"))
	}()

	// 读取出 wc 中写入的数据。
	bs, err := io.ReadAll(rc)

	// 处理 bs 和 err。
	_, _ = bs, err
}

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL