Golang学习(8)——io 包

1160636144 · · 442 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

Golang学习聽-聽io聽包

--------------------

先说一下接口,Go 语言中的接口很简单,在 Go 语言的 io 包中有这样一个函数:

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

这个函数可以把对象 r 中的数据读出来,然后存入一个缓冲区 buf 中,以便其它代码可以处理 buf 中的数据。

这里有个问题,ReadFull 函数究竟可以读取哪些对象的数据?可以读文件中的数据吗?可以读网络中的数据吗?可以读数据库中的数据吗?可以读磁盘中的扇区吗?可以读内存中的数据吗?

答案是: ReadFull 可以读取任何对象的数据,但是有个前提,就是这个对象必须符合 Reader 的标准。Reader 的标准是什么呢?下面是 Reader 的定义:

type Reader interface {

聽聽聽聽Read(p []byte) (n int, err error)

}

从上面的定义可以看出,Reader 的标准很简单,只要某个对象实现了 Read 方法,这个对象就符合了 Reader 的标准,就可以被 ReadFull 读取。太简单了,只需要实现 Read 方法,不需要做其它任何事情。下面我们就来定义一个自己的类型,然后实现 Read 方法:

--------------------

// 定义一个 Ustr 类型

type Ustr struct {聽

聽聽聽聽s string 聽// 数据流

聽聽聽聽i int聽聽 聽 // 读写位置

}

// 根据字符串创建 Ustr 对象

func聽NewUstr(s string) *Ustr {

聽聽聽聽return &Ustr{s, 0}

}

// 获取未读取部分的数据长度

func (s *Ustr) Len() int {

聽聽聽聽returnlen(s.s) - s.i

}

// 实现 Ustr 类型的 Read 方法

func (s *Ustr) Read(p []byte) (n int, err error) {

聽聽聽聽for ; s.i < len(s.s) && n < len(p); s.i++ {

聽聽聽聽聽聽聽聽c := s.s[s.i]

聽聽聽聽聽聽聽聽// 将小写字母转换为大写字母,然后写入 p 中

聽聽聽聽聽聽聽聽if'a' <= c && c <= 'z' {聽

聽聽聽聽聽聽聽聽聽聽聽聽p[n] = c + 'A' - 'a'

聽聽聽聽聽聽聽聽} else {

聽聽聽聽聽聽聽聽聽聽聽聽p[n] = c聽

聽聽聽聽聽聽聽聽}

聽聽聽聽聽聽聽聽n++

聽聽聽聽}

聽聽聽聽// 根据读取的字节数设置返回值

聽聽聽聽if n == 0 {

聽聽聽聽聽聽聽聽return n, io.EOF

聽聽聽聽}

聽聽聽聽return n, nil

}

接下来,我们就可以用 ReadFull 方法读取 Ustr 对象的数据了:

func聽main() {

聽聽聽聽s := NewUstr("Hello World!") // 创建 Ustr 对象 s

聽聽聽聽buf := make([]byte, s.Len()) // 创建缓冲区 buf

聽聽聽聽n, err := io.ReadFull(s, buf)// 将 s 中的数据读取到 buf 中

聽聽聽聽fmt.Printf("%s\n", buf) 聽聽聽聽聽// HELLO WORLD!

聽聽聽聽fmt.Println(n, err) 聽 聽 聽 聽 聽// 12 <nil>

}

--------------------

我们很快就实现了 Reader 的要求,这个 Reader 就是一个接口,接口就是一个标准,一个要求,一个规定,这个规定就是“要实现接口中的方法”。只要某个对象符合 Reader 接口的要求,那么这个对象就可以当作 Reader 接口来使用,就可以传递给 ReadFull 方法。

所以,只要文件对象实现了 Read 方法,那么 ReadFull 就可以读取文件中的数据,只要网络对象实现了 Read 方法,ReadFull 就可以读取网络中的数据,只要数据库实现了 Read 方法,ReadFull 就可以读取数据库中的数据,只要磁盘对象实现了 Read 方法,ReadFull 就可以读磁盘中的数据,只要内存对象实现了 Read 方法,ReadFull 就可以读取内存中的数据,只要任何一个对象实现了 Read 方法,ReadFull 就可以读取该对象的数据。

在 io 包中,定义了许多基本的接口类型,Go 语言的标准库中大量使用了这些接口(就像 ReadFull 一样使用它们),下面我们就来看一看都有哪些接口:

--------------------

// Reader 接口包装了基本的 Read 方法,用于输出自身的数据。

// Read 方法用于将对象的数据流读入到 p 中,返回读取的字节数和遇到的错误。

// 在没有遇到读取错误的情况下:

// 1、如果读到了数据(n > 0),则 err 应该返回 nil。

// 2、如果数据被读空,没有数据可读(n == 0),则 err 应该返回 EOF。

// 如果遇到读取错误,则 err 应该返回相应的错误信息。

type Reader interface { 聽 聽聽

聽聽聽聽Read(p []byte) (n int, err error)聽

}

--------------------

// Writer 接口包装了基本的 Write 方法,用于将数据存入自身。

// Write 方法用于将 p 中的数据写入到对象的数据流中,

// 返回写入的字节数和遇到的错误。

// 如果 p 中的数据全部被写入,则 err 应该返回 nil。

// 如果 p 中的数据无法被全部写入,则 err 应该返回相应的错误信息。

type Writer interface { 聽 聽聽

聽聽聽聽Write(p []byte) (n int, err error)聽

}

--------------------

// Closer 接口包装了基本的 Close 方法,用于关闭数据读写。

// Close 一般用于关闭文件,关闭通道,关闭连接,关闭数据库等

type Closer interface { 聽 聽聽

聽聽聽聽Close() error

}

--------------------

// Seeker 接口包装了基本的 Seek 方法,用于移动数据的读写指针。

// Seek 设置下一次读写操作的指针位置,每次的读写操作都是从指针位置开始的。

// whence 的含义:// 如果 whence 为 0:表示从数据的开头开始移动指针。

// 如果 whence 为 1:表示从数据的当前指针位置开始移动指针。

// 如果 whence 为 2:表示从数据的尾部开始移动指针。

// offset 是指针移动的偏移量。

// 返回新指针位置和遇到的错误。

type Seeker interface { 聽 聽聽

聽聽聽聽Seek(offset int64, whence int) (ret int64, err error)

}

--------------------

// 下面是这些接口的组合接口

type ReadWriter interface { 聽 聽聽

聽聽聽聽Reader 聽 聽聽

聽聽聽聽Writer

}

type ReadSeeker interface { 聽 聽聽

聽聽聽聽Reader 聽 聽聽

聽聽聽聽Seeker聽

}

type WriteSeeker interface { 聽 聽聽

聽聽聽聽Writer 聽 聽聽

聽聽聽聽Seeker聽

}

type ReadWriteSeeker interface { 聽 聽聽

聽聽聽聽Reader 聽 聽聽

聽聽聽聽Writer 聽 聽聽

聽聽聽聽Seeker聽

}

type ReadCloser interface { 聽 聽聽

聽聽聽聽Reader 聽 聽聽

聽聽聽聽Closer聽

}

type WriteCloser interface { 聽 聽聽

聽聽聽聽Writer 聽 聽聽

聽聽聽聽Closer聽

}

type ReadWriteCloser interface { 聽 聽聽

聽聽聽聽Reader 聽 聽聽

聽聽聽聽Writer 聽 聽聽

聽聽聽聽Closer聽

}

--------------------

// ReaderFrom 接口包装了基本的 ReadFrom 方法,用于从 r 中读取数据存入自身。

// 直到遇到 EOF 或读取出错为止,返回读取的字节数和遇到的错误。

type ReaderFrom interface { 聽 聽聽

聽聽聽聽ReadFrom(r Reader) (n int64, err error)

}

--------------------

// WriterTo 接口包装了基本的 WriteTo 方法,用于将自身的数据写入 w 中。

// 直到数据全部写入完毕或遇到错误为止,返回写入的字节数和遇到的错误。

type WriterTo interface { 聽 聽聽

聽聽聽聽WriteTo(w Writer) (n int64, err error)聽

}

--------------------

// ReaderAt 接口包装了基本的 ReadAt 方法,用于将自身的数据写入 p 中。

// ReadAt 忽略之前的读写位置,从起始位置的 off 偏移处开始读取。

//// 返回写入的字节数和遇到的错误,如果 p 被写满,则 err 会返回 nil。如果 p 没

// 有被写满,则会返回一个错误信息用于说明为什么没有写满(比如 io.EOF)。在这

// 方面 ReadAt 比 Read 更严格。如果 p 被写满的同时,自身的数据也刚好被读完,

// 则 err 即可以返回 nil 也可以返回 io.EOF。

//// 即使不能将 p 填满,ReadAt 在被调用时也可能会使用整个 p 的空间作为缓存空间。

// 如果 ReadAt 自身的数据是从其它地方(比如网络)获取数的,那么在写入 p 的时

// 候,如果没有把 p 写满(比如网络延时),则 ReadAt 会阻塞,直到获取更多的数

// 据把 p 写满,或者所有数据都获取完毕,或者遇到读取错误(比如超时)时才返回。

// 在这方面,ReadAt 和 Read 是不同的。

//// 如果 ReadAt 读取的对象是某个有偏移量的底层数据流时,则 ReadAt 方法既不能影

// 响底层的偏移量,也不应该被底层的偏移量影响。

//// ReadAt 的调用者可以对同一数据流并行执行 ReadAt 方法。

//// ReaderAt 的实现者不应该持有 p。

type ReaderAt interface { 聽 聽聽

聽聽聽聽ReadAt(p []byte, off int64) (n int, err error)聽

}

--------------------

// WriterAt 接口包装了基本的 WriteAt 方法,用于将 p 中的数据写入自身。

// ReadAt 忽略之前的读写位置,从起始位置的 off 偏移处开始写入。

//// 返回写入的字节数和遇到的错误。如果 p 没有被读完,则必须返回一个 err 值来说

// 明为什么没有读完。

//// 如果 WriterAt 写入的对象是某个有偏移量的底层数据流时,则 ReadAt 方法既不能

// 影响底层的偏移量,也不应该被底层的偏移量影响。

//// WriterAt 的调用者可以对同一数据流的不同区段并行执行 WriteAt 方法。

//// WriterAt 的实现者不应该持有 p。

type WriterAt interface { 聽 聽聽

聽聽聽聽WriteAt(p []byte, off int64) (n int, err error)聽

}

--------------------

// ByteReader 接口包装了基本的 ReadByte 方法,用于从自身读出一个字节。

// 返回读出的字节和遇到的错误。

type ByteReader interface { 聽 聽聽

聽聽聽聽ReadByte() (c byte, err error)聽

}

--------------------

// ByteScanner 在 ByteReader 的基础上增加了一个 UnreadByte 方法,用于撤消最后

// 一次的 ReadByte 操作,以便下次的 ReadByte 操作可以读出与前一次一样的数据。

// UnreadByte 之前必须是 ReadByte 才能撤消成功,否则可能会返回一个错误信息(根

// 据不同的需求,UnreadByte 也可能返回 nil,允许随意调用 UnreadByte,但只有最

// 后一次的 ReadByte 可以被撤销,其它 UnreadByte 不执行任何操作)。

type ByteScanner interface { 聽 聽聽

聽聽聽聽ByteReader 聽UnreadByte() error

}

--------------------

// ByteWriter 接口包装了基本的 WriteByte 方法,用于将一个字节写入自身

// 返回遇到的错误

type ByteWriter interface { 聽 聽聽

聽聽聽聽WriteByte(c byte) error

}

--------------------

// RuneReader 接口包装了基本的 ReadRune 方法,用于从自身读取一个 UTF-8 编码的

// 字符到 r 中。

// 返回读取的字符、字符的编码长度和遇到的错误。

type RuneReader interface { 聽 聽聽

聽聽聽聽ReadRune() (r rune, size int, err error)聽

}

--------------------

// RuneScanner 在 RuneReader 的基础上增加了一个 UnreadRune 方法,用于撤消最后

// 一次的 ReadRune 操作,以便下次的 ReadRune 操作可以读出与前一次一样的数据。

// UnreadRune 之前必须是 ReadRune 才能撤消成功,否则可能会返回一个错误信息(根

// 据不同的需求,UnreadRune 也可能返回 nil,允许随意调用 UnreadRune,但只有最

// 后一次的 ReadRune 可以被撤销,其它 UnreadRune 不执行任何操作)。

type RuneScanner interface { 聽 聽聽

聽聽聽聽RuneReader 聽 聽 UnreadRune() error

}

--------------------

// bytes.NewBuffer 实现了很多基本的接口,可以通过 bytes 包学习接口的实现

funcmain() {聽

聽聽聽聽buf := bytes.NewBuffer([]byte("Hello World!"))聽

聽聽聽聽b := make([]byte, buf.Len())聽

聽聽聽聽n, err := buf.Read(b)聽

聽聽聽聽fmt.Printf("%s 聽 %v\n", b[:n], err) // Hello World! 聽 <nil>

聽聽聽聽buf.WriteString("ABCDEFG\n")聽

聽聽聽聽buf.WriteTo(os.Stdout) // ABCDEFG

聽聽聽聽n, err = buf.Write(b)聽

聽聽聽聽fmt.Printf("%d %s %v\n", n, buf.String(), err) //12 Hello World! <nil>

聽聽聽聽c, err := buf.ReadByte()聽

聽聽聽聽fmt.Printf("%c %s %v\n", c, buf.String(), err) // H ello World! <nil>

聽聽聽聽c, err = buf.ReadByte()聽

聽聽聽聽fmt.Printf("%c %s %v\n", c, buf.String(), err) // e llo World! 聽 <nil>

聽聽聽聽err = buf.UnreadByte()聽

聽聽聽聽fmt.Printf("%s 聽 %v\n", buf.String(), err) // ello World! 聽 <nil>

聽聽聽聽err = buf.UnreadByte()聽

聽聽聽聽fmt.Printf("%s 聽 %v\n", buf.String(), err)

//ello World! bytes.Buffer: UnreadByte: previous operation was not a read

}

--------------------

// WriteString 将字符串 s 写入到 w 中,返回写入的字节数和遇到的错误。

// 如果 w 实现了 WriteString 方法,则优先使用该方法将 s 写入 w 中。

// 否则,将 s 转换为 []byte,然后调用 w.Write 方法将数据写入 w 中。

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

// ReadAtLeast 从 r 中读取数据到 buf 中,要求至少读取 min 个字节。

// 返回读取的字节数和遇到的错误。

// 如果 min 超出了 buf 的容量,则 err 返回 io.ErrShortBuffer,否则:

// 1、读出的数据长度 == 0 聽,则 err 返回 EOF。

// 2、读出的数据长度 < 聽min,则 err 返回 io.ErrUnexpectedEOF。

// 3、读出的数据长度 >= min,则 err 返回 nil。

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

// ReadFull 的功能和 ReadAtLeast 一样,只不过 min = len(buf)

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

// CopyN 从 src 中复制 n 个字节的数据到 dst 中,返回复制的字节数和遇到的错误。

// 只有当 written = n 时,err 才返回 nil。

// 如果 dst 实现了 ReadFrom 方法,则优先调用该方法执行复制操作。

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

// Copy 从 src 中复制数据到 dst 中,直到所有数据都复制完毕,返回复制的字节数和

// 遇到的错误。如果复制过程成功结束,则 err 返回 nil,而不是 EOF,因为 Copy 的

// 定义为“直到所有数据都复制完毕”,所以不会将 EOF 视为错误返回。

// 如果 src 实现了 WriteTo 方法,则调用 src.WriteTo(dst) 复制数据,否则

// 如果 dst 实现了 ReadeFrom 方法,则调用 dst.ReadeFrom(src) 复制数据

func聽Copy(dst Writer, src Reader) (written int64, err error)

// CopyBuffer 相当于 Copy,只不 Copy 在执行的过程中会创建一个临时的缓冲区来中

// 转数据,而 CopyBuffer 则可以单独提供一个缓冲区,让多个复制操作共用同一个缓

// 冲区,避免每次复制操作都创建新的缓冲区。如果 buf == nil,则 CopyBuffer 会

// 自动创建缓冲区。

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

--------------------

// 示例:WriteString、ReadAtLeast、ReadFull

func聽main() {聽

聽聽聽聽io.WriteString(os.Stdout, "Hello World!\n") // Hello World!

聽聽聽聽r := strings.NewReader("Hello World!")聽

聽聽聽聽b := make([]byte, 15)聽

聽聽聽聽n, err := io.ReadAtLeast(r, b, 20)聽

聽聽聽聽fmt.Printf("%q 聽 %d 聽 %v\n", b[:n], n, err) // "" 聽 0 聽 short buffer

聽聽聽聽r.Seek(0, 0)聽

聽聽聽聽b = make([]byte, 15)聽

聽聽聽聽n, err = io.ReadFull(r, b)聽

聽 fmt.Printf("%q %d %v\n", b[:n], n, err)// "Hello World!" 12 unexpected EOF

}

--------------------

// 示例:CopyN、Copy、CopyBuffer

func聽main() {聽

聽聽聽聽r := strings.NewReader("Hello World!")

聽聽聽聽buf := make([]byte, 32)聽

聽聽聽聽n, err := io.CopyN(os.Stdout, r, 5) // Hello

聽聽聽聽fmt.Printf("\n%d 聽 %v\n\n", n, err) // 5 聽 <nil>

聽聽聽聽r.Seek(0, 0)聽

聽聽聽聽n, err = io.Copy(os.Stdout, r)聽 聽 聽 // Hello World!

聽聽聽聽fmt.Printf("\n%d 聽 %v\n\n", n, err) // 12 聽 <nil>

聽聽聽聽r.Seek(0, 0)聽

聽聽聽聽r2 := strings.NewReader("ABCDEFG")聽

聽聽聽聽r3 := strings.NewReader("abcdefg")聽

聽聽聽聽n, err = io.CopyBuffer(os.Stdout, r, buf) // Hello World!

聽聽聽聽fmt.Printf("\n%d 聽 %v\n", n, err)聽 聽 聽 聽 聽// 12 聽 <nil>

聽聽聽聽n, err = io.CopyBuffer(os.Stdout, r2, buf) // ABCDEFG

聽聽聽聽fmt.Printf("\n%d 聽 %v\n", n, err)聽 聽 聽 聽 聽 // 7 聽 <nil>

聽聽聽聽n, err = io.CopyBuffer(os.Stdout, r3, buf) // abcdefg

聽聽聽聽fmt.Printf("\n%d 聽 %v\n", n, err)聽 聽 聽 聽 聽 // 7 聽 <nil>

}

--------------------

// LimitReader 对 r 进行封装,使其最多只能读取 n 个字节的数据。相当于对 r 做了

// 一个切片 r[:n] 返回。底层实现是一个 *LimitedReader(只有一个 Read 方法)。

func聽LimitReader(r Reader, n int64) Reader

// MultiReader 将多个 Reader 封装成一个单独的 Reader,多个 Reader 会按顺序读

// 取,当多个 Reader 都返回 EOF 之后,单独的 Reader 才返回 EOF,否则返回读取

// 过程中遇到的任何错误。

funcMultiReader(readers ...Reader) Reader

// MultiReader 将向自身写入的数据同步写入到所有 writers 中。

funcMultiWriter(writers ...Writer) Writer

// TeeReader 对 r 进行封装,使 r 在读取数据的同时,自动向 w 中写入数据。

// 它是一个无缓冲的 Reader,所以对 w 的写入操作必须在 r 的 Read 操作结束

// 之前完成。所有写入时遇到的错误都会被作为 Read 方法的 err 返回。

func聽TeeReader(r Reader, w Writer) Reader

--------------------

// 示例 LimitReader

func聽main() {聽

聽聽聽聽r := strings.NewReader("Hello World!")聽

聽聽聽聽lr := io.LimitReader(r, 5)聽

聽聽聽聽n, err := io.Copy(os.Stdout, lr) 聽// Hello

聽聽聽聽fmt.Printf("\n%d 聽 %v\n", n, err) // 5 聽 <nil>

}

--------------------

// 示例 MultiReader

func聽main() {聽

聽聽聽聽r1 := strings.NewReader("Hello World!")聽

聽聽聽聽r2 := strings.NewReader("ABCDEFG")聽

聽聽聽聽r3 := strings.NewReader("abcdefg")聽

聽聽聽聽b := make([]byte, 15)聽

聽聽聽聽mr := io.MultiReader(r1, r2, r3)

聽聽聽聽for n, err := 0, error(nil); err == nil; {聽

聽聽聽聽聽聽聽聽n, err = mr.Read(b) fmt.Printf("%q\n", b[:n])

聽聽聽聽}

聽聽聽聽// "Hello World!"// "ABCDEFG"// "abcdefg"// ""

聽聽聽聽r1.Seek(0, 0)聽

聽聽聽聽r2.Seek(0, 0)聽

聽聽聽聽r3.Seek(0, 0)聽

聽聽聽聽mr = io.MultiReader(r1, r2, r3)聽

聽聽聽聽io.Copy(os.Stdout, mr)

聽聽聽聽// Hello World!ABCDEFGabcdefg

}

--------------------

// 示例 MultiWriter

func聽main() {聽

聽聽聽聽r := strings.NewReader("Hello World!\n")聽

聽聽聽聽mw := io.MultiWriter(os.Stdout, os.Stdout, os.Stdout)聽

聽聽聽聽r.WriteTo(mw)

聽聽聽聽// Hello World!

聽聽聽聽// Hello World!

聽聽聽聽// Hello World!

}

// 示例 TeeReader

func聽main() {聽

聽聽聽聽r := strings.NewReader("Hello World!")聽

聽聽聽聽b := make([]byte, 15)聽

聽聽聽聽tr := io.TeeReader(r, os.Stdout)聽

聽聽聽聽n, err := tr.Read(b)聽 聽 聽 聽 聽 聽 聽 聽 聽 // Hello World!

聽聽聽聽fmt.Printf("\n%s 聽 %v\n", b[:n], err) // Hello World! 聽 <nil>

}

--------------------

// NewSectionReader 对 r 进行封装,使其只能从 off 位置开始读取,最多只能读取 n

// 个字节的的数据。相当于对 r 做了一个切片 r[off:off+n] 返回。

// 底层实现是一个 *SectionReader。

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

// SectionReader 实现了如下接口:

// io.Reader

// io.ReaderAt

// io.Seeker

// Size 返回允许读取部分的大小(即切片的长度 n)

func (s *SectionReader) Size()

--------------------

// 示例 SectionReaderfuncmain() { r := strings.NewReader("Hello World!") sr := io.NewSectionReader(r, 6, 5) n, err := io.Copy(os.Stdout, sr)聽 聽 聽 聽 聽 聽 聽 聽 聽 // World fmt.Printf("\n%d 聽 %d 聽 %v\n", sr.Size(), n, err) // 5 聽 5 聽 <nil>}

--------------------

// Pipe 在内存中创建一个同步管道,用于不同区域的代码之间相互传递数据。

// 返回的 *PipeReader 用于从管道中读取数据,*PipeWriter 用于向管道中写入数据。

// 管道没有缓冲区,读写操作可能会被阻塞。可以安全的对管道进行并行的读、写或关闭

// 操作,读写操作会依次执行,Close 会在被阻塞的 I/O 操作结束之后完成。

func聽Pipe() (*PipeReader, *PipeWriter)

// 从管道中读取数据,如果管道被关闭,则会返会一个错误信息:

// 1、如果写入端通过 CloseWithError 方法关闭了管道,则返回关闭时传入的错误信息。

// 2、如果写入端通过 Close 方法关闭了管道,则返回 io.EOF。

// 3、如果是读取端关闭了管道,则返回 io.ErrClosedPipe。

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

// 关闭管道

func (r *PipeReader) Close() error

// 关闭管道并传入错误信息。

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

// 向管道中写入数据,如果管道被关闭,则会返会一个错误信息:

// 1、如果读取端通过 CloseWithError 方法关闭了管道,则返回关闭时传入的错误信息。

// 2、如果读取端通过 Close 方法关闭了管道,则返回 io.ErrClosedPipe。

// 3、如果是写入端关闭了管道,则返回 io.ErrClosedPipe。

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

// 关闭管道

func (w *PipeWriter) Close() error

// 关闭管道并传入错误信息。

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

--------------------

// 示例:管道(读取端关闭)

func聽main() {聽

聽聽聽聽r, w := io.Pipe()

聽聽聽聽// 启用一个例程进行读取

聽聽聽聽gofunc() {聽

聽聽聽聽聽聽聽聽buf := make([]byte, 5)

聽聽聽聽聽聽聽聽for n, err := 0, error(nil); err == nil; {聽

聽聽聽聽聽聽聽聽聽聽聽聽n, err = r.Read(buf)聽

聽聽聽聽聽聽聽聽聽聽聽聽r.CloseWithError(errors.New("管道被读取端关闭"))聽

聽聽聽聽聽聽聽聽聽聽聽聽fmt.Printf("读取:%d, %v, %s\n", n, err, buf[:n])

聽聽聽聽聽聽聽聽}

聽聽聽聽}()

聽聽聽聽// 主例程进行写入

聽聽聽聽n, err := w.Write([]byte("Hello World !"))

聽聽聽聽fmt.Printf("写入:%d, %v\n", n, err)聽

}

--------------------

// 示例:管道(写入端关闭)

func聽main() {聽

聽聽聽聽r, w := io.Pipe() // 启用一个例程进行读取

聽聽聽聽gofunc() {聽

聽聽聽聽聽聽聽聽buf := make([]byte, 5)

聽聽聽聽聽聽聽聽for n, err := 0, error(nil); err == nil; {聽

聽聽聽聽聽聽聽聽聽聽聽聽n, err = r.Read(buf)聽

聽聽聽聽聽聽聽聽聽聽聽聽fmt.Printf("读取:%d, %v, %s\n", n, err, buf[:n])聽

聽聽聽聽聽聽聽聽}

聽聽聽聽}()

聽聽聽聽// 主例程进行写入

聽聽聽聽n, err := w.Write([]byte("Hello World !"))聽

聽聽聽聽fmt.Printf("写入:%d, %v\n", n, err)聽

聽聽聽聽w.CloseWithError(errors.New("管道被写入端关闭"))聽

聽聽聽聽n, err = w.Write([]byte("Hello World !"))聽

聽聽聽聽fmt.Printf("写入:%d, %v\n", n, err)聽

聽聽聽聽time.Sleep(time.Second * 1)

}



有疑问加站长微信联系(非本文作者)

本文来自:51CTO博客

感谢作者:1160636144

查看原文:Golang学习(8)——io 包

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:701969077

442 次点击  
加入收藏 微博
上一篇:Plan 9安装Go
下一篇:golang基础知识
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传