Go语言基础(三)输入输出接口
本文主要介绍了Go语言输入输出接口。
关键词:golang
基本的IO接口
Reader接口
1 | type Reader interface { |
将len(p)个字节读入到p中,返回读取的字节数n以及任何的错误。即使Read返回的n<len(p),他也会在调用过程中占用len(p)个字节作为暂存空间。若可读取的数据不到len(p)个字节,会返回可用数据,而不是等待更多数据。
当Read在成功读取n个字节后,遇到一个错误或者EOF,会返回读取的字节数,可能会在本次的调用中返回一个non-nil错误,或者在下一次调用中返回这个错误(n为0)。一般情况下,Reader会返回非0字节数n,若n=len(p)个字节从输入源内的结尾处由Read返回,Read可能返回err==EOF或者err==nil,并且之后的Read()都应该返回(n:0, err:EOF).
调用者在考虑错误之前应当首先处理返回的数据。这样做可以正确的处理在读取一些字节后产生的I/O,允许EOF出现。
Reader的接口方法集只包含一个Read方法,实现了Read方法的类型都满足io.Reader接口,也就是说在需要io.Reader的地方,可以传递实现了Read()方法的实例。
举例说明Reader接口的方法:
1 | func ReadFrom(reader io.Reader, num int)([]byte, error) { |
ReadFrom函数将io.Reader作为参数,ReadForm可以从任意的地方读取数据,只要来源实现了io.Reader接口。可以从标准输入、文件、字符串读取数据:
1 | // 标准输入 |
Writer 接口
1 | type Writer interface { |
将len(p)个字节写入基本数据流中,返回从p中被写入的字节数n,以及任何遇到的引起的提前停止的错误。若Write返回的n<len(p),就必须返回一个非nil的错误。
所有实现了Write方法的类型都实现了io.Writer接口。
1 | func Println(a ...interface{})(n int, err error) { |
实现了Reader接口或者Writer接口的类型
- os.File同时实现了io.Reader和io.Writer
- strings.Reader实现了io.Reader
- bufio.Reader/Writer 分别实现了 io.Reader 和 io.Writer
- bytes.Buffer同时实现了io.Reader和io.Writer
- bytes.Reader实现了io.Reader
- compress/gzip.Reader/Writer 分别实现了io.Reader和io.Writer
- crypto/cipher.StreamReader/StreamWriter 分别实现了 io.Reader 和 io.Writer
- crypto/tls.Conn同时实现了io.Reader和io.Writer
- encoding/csv.Reader/Writer 分别实现了 io.Reader 和 io.Writer
- mine/multpart.Part实现了io.Reader
- net/conn分别实现了io.Reader和io.Writer(Conn接口定义了Read/Write)
Closer接口
1 | type Closer interface { |
该接口比较简单,只有一个close()方法,用于关闭数据流;
文件、归档、数据库链接、Socket等需要手动关闭的资源都实现了Closer接口;
实际编程中通常将Close方法的调用放在defer语句中。
ioutil 方便的IO操作函数集
NopCloser函数
有时候我们需要传递一个io.ReadCloser实例,而我们现在有一个io.Reader实例。
使用NopCloser包装一个Reader,返回一个io.ReaderCloser,相应的Close方法什么也不做,只是返回nil;
比如在标准库net/http包中的NewRequest,接收一个io.Reader的body,实际上Request的Body的类型是io.ReadCloser,因此代码内部做了判断:
如果传入的io.Reader也实现了io.ReaderCloser接口,则转换,否则通过ioutil.NopCloser包装一下。
ReadAll函数
1 | func ReadAll(r io.Reader)([]byte, error) |
一次性读取io.Reader中的所有数据
ReadDir函数
输出某目录下面的所有文件(包括子目录)
ReadFile和WriteFile函数
ReadFile读取整个文件的内容。
1 | func ReadFile(filename string)([]byte, error) |
从指定的filename的文件中读取数据并返回文件的内容,成功的调用返回的err为nil而非EOF。因为本函数定义为读取整个文件不会将读取的EOF视为报告的错误
WriteFile将data写入filename文件中,当文件不存在时会根据perm指定的权限创建一个,文件存在时会先清空内容,对于perm参数,可以指定为0666.
TempDir和TempFile函数
一般操作系统都会允许创建临时目录,比如linux下的/tmp目录。
通过TempDir可以创建一个临时目录,用于存放编译过程的临时目录
1 | b.work, err = ioutil.TempDir("", "tmp") |
如果第一个参数为空,表面在系统默认的临时目录中创建临时目录,第二个参数指定临时目录的前缀,函数返回临时目录的路径;
1 | f1, err := ioutil.TempFile("", "gofmt") |
创建者创建的临时变量和临时目录要负责删除这些临时目录和文件,比如删除临时文件:
1 | defer func() { |