golang 中io包用法(一)

golang 中io包用法(一),第1张

概述本文转自Golove博客:http://www.cnblogs.com/golove/p/3276678.html  io 包为I/O原语提供了基础的接口.它主要包装了这些原语的已有实现,如 os 包中的那些,抽象成函数性的共享公共接口,加上一些其它相关的原语。 由于这些接口和原语以不同的实现包装了低级 *** 作,因此除非另行通知,否则客户不应假定它们对于并行执行是安全的。 在io包中最重要的是两个接口

本文转自Golove博客:http://www.cnblogs.com/golove/p/3276678.html 


io 包为I/O原语提供了基础的接口.它主要包装了这些原语的已有实现,如 os 包中的那些,抽象成函数性的共享公共接口,加上一些其它相关的原语。

由于这些接口和原语以不同的实现包装了低级 *** 作,因此除非另行通知,否则客户不应假定它们对于并行执行是安全的。

在io包中最重要的是两个接口:Reader和Writer接口,首先来介绍这两个接口.

@H_403_18@type Reader interface { Read(p []byte) (n int,err error)}

 

Reader 接口包装了基本的 Read 方法。

Read 将 len(p) 个字节读取到 p 中。它返回读取的字节数 n(0 <= n <= len(p))以及任何遇到的错误。即使 Read 返回的 n < len(p),它也会在调用过程中使用 p的全部作为暂存空间。若一些数据可用但不到 len(p) 个字节,Read 会照例返回可用的东西,而不是等待更多。

当 Read 在成功读取 n > 0 个字节后遇到一个错误或 EOF 情况,它就会返回读取的字节数。它会从相同的调用中返回(非nil的)错误或从随后的调用中返回错误(和 n == 0)。这种一般情况的一个例子就是 Reader 在输入流结束时会返回一个非零的字节数,可能的返回不是 err == EOF 就是 err == nil。无论如何,下一个 Read 都应当返回 0,EOF。

调用者应当总在考虑到错误 err 前处理 n > 0 的字节。这样做可以在读取一些字节,以及允许的 EOF 行为后正确地处理I/O错误。

Read 的实现会阻止返回零字节的计数和一个 nil 错误,调用者应将这种情况视作空 *** 作。

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

 

Writer 接口包装了基本的 Write 方法。

Write 将 len(p) 个字节从 p 中写入到基本数据流中。它返回从 p 中被写入的字节数n(0 <= n <= len(p))以及任何遇到的引起写入提前停止的错误。若 Write 返回的n < len(p),它就必须返回一个非nil的错误。Write 不能修改此切片的数据,即便它是临时的。

 

Io包中的函数(方法):

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

 



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

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

  答案是 ReadFull 可以读取任何对象的数据,但是有个前提,就是这个对象必须符合 Reader 的标准。

  Reader 的标准是什么呢?下面是 Reader 的定义:

@H_403_18@type Reader interface {Read(p []byte) (n int,err error)}

 


  从上面的定义可以看出,Reader 的标准很简单,只要某个对象实现了 Read 方法,这个对象就符合了 Reader 的标准,就可以被 ReadFull 读取。

  太简单了,只需要实现 Read 方法,不需要做其它任何事情。下面我们就来定义一个自己的类型,然后实现 Read 方法:

@H_403_18@// 定义一个 Ustr 类型(以 string 为基类型)type Ustr string// 实现 Ustr 类型的 Read 方法func (s Ustr) Read(p []byte) (n int,err error) { i,ls,lp := 0,len(s),len(p) for ; i < ls && i < lp; i++ { // 将小写字母转换为@R_419_6717@,然后写入 p 中 if s[i] >= ‘a‘ && s[i] <= ‘z‘ { p[i] = s[i] + ‘A‘ - ‘a‘ } else { p[i] = s[i] } } // 根据读取的字节数设置返回值 switch i { case lp: return i,nil case ls: return i,io.EOF default: return i,errors.New("Read Fail") }}

 


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

@H_403_18@func main() { us := Ustr("Hello World!") // 创建 Ustr 对象 us buf := make([]byte,32) // 创建缓冲区 buf n,err := io.ReadFull(us,buf) // 将 us 中的数据读取到 buf 中 fmt.Printf("%s\n",buf) // 显示 buf 中的内容 // Hello World! fmt.Println(n,err) // 显示返回值 // 12 unexpected EOF}

 


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

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

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

@H_403_18@// Writer 接口封装了基本的 Write 方法// Write 方法用于将 p 中的数据写入到对象的数据流中// 返回写入的字节数 n (0 <= n <= len(p)) 和写入时遇到的任何错误// 如果 p 中的数据全部被写入,则 err 应该返回 nil// 如果 p 中的数据无法被全部写入,则 err 应该返回相应的错误信息// Writer 用来存入数据type Writer interface { Write(p []byte) (n int,err error)}------------------------------------------------------------// Closer 接口封装了基本的 Close 方法// Close 一般用于关闭文件,关闭连接,关闭数据库等// Close 用来关闭数据type Closer interface { Close() error}------------------------------------------------------------// Seeker 接口封装了基本的 Seek 方法// Seek 设置下一次读写 *** 作的指针位置,每次的读写 *** 作都是从指针位置开始的// whence 的含义:// 如果 whence 为 0:表示从数据的开头开始移动指针// 如果 whence 为 1:表示从数据的当前指针位置开始移动指针// 如果 whence 为 2:表示从数据的尾部开始移动指针// offset 是指针移动的偏移量// 返回移动后的指针位置和移动过程中遇到的任何错误// Seeker 用来移动数据的读写指针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 方法// ReadFrom 从 r 中读取数据到对象的数据流中// 直到 r 返回 EOF 或 r 出现读取错误为止// 返回值 n 是读取的字节数// 返回值 err 就是 r 的返回值 err// ReadFrom 用来读出 r 中的数据type ReaderFrom interface { ReadFrom(r Reader) (n int64,err error)}------------------------------------------------------------// WriterTo 接口封装了基本的 Writeto 方法// WriterTo 将对象的数据流写入到 w 中// 直到对象的数据流全部写入完毕或遇到写入错误为止// 返回值 n 是写入的字节数// 返回值 err 就是 w 的返回值 err// Writeto 用来将数据写入 w 中type WriterTo interface { Writeto(w Writer) (n int64,err error)}------------------------------------------------------------// ReaderAt 接口封装了基本的 ReadAt 方法// ReadAt 从对象数据流的 off 处读出数据到 p 中// 忽略数据的读写指针,从数据的起始位置偏移 off 处开始读取// 如果对象的数据流只有部分可用,不足以填满 p// 则 ReadAt 将等待所有数据可用之后,继续向 p 中写入// 直到将 p 填满后再返回// 在这点上 ReadAt 要比 Read 更严格// 返回读取的字节数 n 和读取时遇到的错误// 如果 n < len(p),则需要返回一个 err 值来说明// 为什么没有将 p 填满(比如 EOF)// 如果 n = len(p),而且对象的数据没有全部读完,则// err 将返回 nil// 如果 n = len(p),而且对象的数据刚好全部读完,则// err 将返回 EOF 或者 nil(不确定)type ReaderAt interface { ReadAt(p []byte,off int64) (n int,err error)}------------------------------------------------------------// Writerat 接口封装了基本的 WriteAt 方法// WriteAt 将 p 中的数据写入到对象数据流的 off 处// 忽略数据的读写指针,从数据的起始位置偏移 off 处开始写入// 返回写入的字节数和写入时遇到的错误// 如果 n < len(p),则必须返回一个 err 值来说明// 为什么没有将 p 完全写入type Writerat interface { WriteAt(p []byte,err error)}------------------------------------------------------------// ByteReader 接口封装了基本的 ReadByte 方法// ReadByte 从对象的数据流中读取一个字节到 c 中// 如果对象的数据流中没有可读数据,则返回一个错误信息type ByteReader interface { ReadByte() (c byte,err error)}------------------------------------------------------------// ByteScanner 在 ByteReader 的基础上增加了一个 UnreadByte 方法// UnreadByte 用于撤消最后一次的 ReadByte *** 作// 即将对象的读写指针移到上次 ReadByte 之前的位置// 如果上一次的 *** 作不是 ReadByte,则 UnreadByte 返回一个错误信息type ByteScanner interface {ByteReaderUnreadByte() error}------------------------------------------------------------// ByteWriter 接口封装了基本的 WriteByte 方法// WriteByte 将一个字节 c 写入到对象的数据流中// 返回写入过程中遇到的任何错误type ByteWriter interface { WriteByte(c byte) error}------------------------------------------------------------// RuneReader 接口封装了基本的 ReadRune 方法// ReadRune 从对象的数据流中读取一个字符到 r 中// 如果对象的数据流中没有可读数据,则返回一个错误信息type RuneReader interface { ReadRune() (r rune,size int,err error)}------------------------------------------------------------// Runescanner 在 RuneReader 的基础上增加了一个 UnreadRune 方法// UnreadRune 用于撤消最后一次的 ReadRune *** 作// 即将对象的读写指针移到上次 ReadRune 之前的位置// 如果上一次的 *** 作不是 ReadRune,则 UnreadRune 返回一个错误信息type Runescanner interface { RuneReader UnreadRune() error}------------------------------------------------------------// bytes.NewBuffer 实现了很多基本的接口,可以通过 bytes 包学习接口的实现func main() { bb := bytes.NewBuffer([]byte("Hello World!")) b := make([]byte,32) bb.Read(b) fmt.Printf("%s\n",b) // Hello World! bb.WriteString("New Data!\n") bb.Writeto(os.Stdout) // New Data! bb.WriteString("Third Data!") bb.ReadByte() fmt.Println(bb.String()) // hird Data! bb.UnreadByte() fmt.Println(bb.String()) // Third Data!}------------------------------------------------------------// 下面是 io 包中的函数------------------------------------------------------------// WriteString 将字符串 s 写入到 w 中// 返回写入的字节数和写入过程中遇到的任何错误// 如果 w 实现了 WriteString 方法// 则调用 w 的 WriteString 方法将 s 写入 w 中// 否则,将 s 转换为 []byte// 然后调用 w.Write 方法将数据写入 w 中func WriteString(w Writer,s string) (n int,err error)func main() { // os.Stdout 实现了 Writer 接口 io.WriteString(os.Stdout,"Hello World!") // Hello World!}------------------------------------------------------------// ReadAtLeast 从 r 中读取数据到 buf 中,要求至少读取 min 个字节// 返回读取的字节数 n 和读取过程中遇到的任何错误// 如果 n < min,则 err 返回 ErrUnexpectedEOF// 如果 r 中无可读数据,则 err 返回 EOF// 如果 min 大于 len(buf),则 err 返回 ErrShortBuffer// 只有当 n >= min 时 err 才返回 nilfunc ReadAtLeast(r Reader,buf []byte,min int) (n int,err error)func main() { r := strings.NewReader("Hello World!") b := make([]byte,32) n,err := io.ReadAtLeast(r,b,20) fmt.Printf("%s\n%d,%v",n,err) // Hello World! // 12,unexpected EOF}------------------------------------------------------------// ReadFull 的功能和 ReadAtLeast 一样,只不过 min = len(buf),其中要求最少读取的字节数目是len(buf),当r中数据少于len(buf)时便会报错func ReadFull(r Reader,err := io.ReadFull(r,b) fmt.Printf("%s\n%d,unexpected EOF}------------------------------------------------------------// copyN 从 src 中复制 n 个字节的数据到 dst 中// 它返回复制的字节数 written 和复制过程中遇到的任何错误// 只有当 written = n 时,err 才返回 nil// 如果 dst 实现了 ReadFrom 方法,则调用 ReadFrom 来执行复制 *** 作func copyN(dst Writer,src Reader,n int64) (written int64,err error)func main() { r := strings.NewReader("Hello World!") n,err := io.copyN(os.Stdout,r,20) fmt.Printf("\n%d,EOF}------------------------------------------------------------// copy 从 src 中复制数据到 dst 中,直到所有数据复制完毕// 返回复制过程中遇到的任何错误// 如果数据复制完毕,则 err 返回 nil,而不是 EOF// 如果 dst 实现了 ReadeFrom 方法,则调用 dst.ReadeFrom(src) 复制数据// 如果 src 实现了 Writeto 方法,则调用 src.Writeto(dst) 复制数据func copy(dst Writer,src Reader) (written int64,err := io.copy(os.Stdout,r) fmt.Printf("\n%d,<nil>}------------------------------------------------------------// limitReader 覆盖了 r 的 Read 方法// 使 r 只能读取 n 个字节的数据,读取完毕后返回 EOFfunc limitReader(r Reader,n int64) Reader// limitedReader 结构用来实现 limitReader 的功能type limitedReader structfunc main() { r := strings.NewReader("Hello World!") lr := io.limitReader(r,5) n,lr,err) // Hello // 5,EOF}------------------------------------------------------------// NewSectionReader 封装 r,并返回 SectionReader 类型的对象// 使 r 只能从 off 的位置读取 n 个字节的数据,读取完毕后返回 EOFfunc NewSectionReader(r ReaderAt,off int64,n int64) *SectionReader// SectionReader 结构用来实现 NewSectionReader 的功能// SectionReader 实现了 Read、Seek、ReadAt、Size 方法type SectionReader struct// Size 返回 s 中被限制读取的字节数func (s *SectionReader) Size()func main() { r := strings.NewReader("Hello World!") sr := io.NewSectionReader(r,sr,err) fmt.Printf("\n%d",sr.Size()) // World // 5,EOF // 5}------------------------------------------------------------// TeeReader 覆盖了 r 的 Read 方法// 使 r 在读取数据的同时,自动向 w 中写入数据// 所有写入时遇到的错误都被作为 err 返回值func TeeReader(r Reader,w Writer) Readerfunc main() { r := strings.NewReader("Hello World!") tr := io.TeeReader(r,os.Stdout) b := make([]byte,32) tr.Read(b) // World World!} 总结

以上是内存溢出为你收集整理的golang 中io包用法(一)全部内容,希望文章能够帮你解决golang 中io包用法(一)所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/langs/1270468.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-06-08
下一篇 2022-06-08

发表评论

登录后才能评论

评论列表(0条)

保存