这篇文章讲什么?不讲什么?
我会从什么是io操作开始,逐步展开golang中的io知识体系;这个过程不会去按顺序介绍io包的所有接口啥的,那样做看似全面,其实很枯燥,看完就是忘完。如果你对IO操作有基础的认识,但是不知道golang中的io是怎么回事,那么下面的介绍会帮助你轻松入门了解io in go!
io操作简单理解就是从某处读/写到某处;比如读取键盘输入,读取文件,输出到终端,输出到一个文件……
go语言的io 包提供了I/O原语的基本接口,我们先看最最基础的2个接口
如上所示,2个接口的定义很简单,都只包含一个方法,下面分别介绍
Read的用法应该还是容易理解,就是用一个p来暂存读取到的数据。任意一个类型只要实现了Read方法就算实现了Reader接口,也就成为了Reader接口的一个实例。如果暂时没有完全理解,等后面看完具体的用例再回过头来看看Read方法吧~
Write 将 len(p) 个字节的数据写入到基本数据流中。它返回从 p 中被写入的字节数 n(0 <= n <= len(p))以及任何遇到的引起写入提前停止的错误。若 Write 返回的 n < len(p),它就必须返回一个非nil的错误。也就是说p里应该全部是需要output的数据,全部完成写操作了就返回len(p)和nil,如果len(p)>n,也就是写中断了,这时候err必须有错误信息。
下面先看一下标准库中实现了io.Writer和io.Reader接口的那些类型是怎么工作的
先看源码中怎么定义File的
注释是说File表示一个打开文件的描述符
File类型实现了十几个接口,其中包括了上面提到的io.Reader和io.Writer
先看一个简单的File读写文件操作(为了简化代码,突出重点,略去了错误处理等非功能代码)
func main() { //打开一个文件,文件里面存的是数字123 f, _ := os.Open("d:\\1.txt") defer f.Close() //用一个长度为5的byte切片来读取数据 b := make([]byte, 5) //n也就是读取到的数据长度 n, _ := f.Read(b) //输出内容是:3 [49 50 51 0 0] 123 fmt.Println(n, b, string(b)) }
func main() { //创建文件 f, _ := os.Create("d:\\666.txt") //待写入的数据 b := []byte("CloudGeek") //执行写操作,n为写入的字符数 n, _ := f.Write(b) //输出结果是:9 fmt.Println(n) }
上述代码很简短,实际文件读取操作的时候也不会这样用,不然就low了;这里只是为了给大家展示os.File类型实现了io.Writer和io.Reader接口,所以对应的Read和Write方法可以实现io操作,参数列表和返回值含义都是和前面介绍接口的时候讲的一样。
func main() {
b, err := ioutil.ReadFile("d:\\1.txt")
if err == nil {
fmt.Println(string(b))
}
}
func main() { //文件不存在会新建,权限通过perm指定,文件存在会被清空后再写入数据 err := ioutil.WriteFile("d:\\3.txt", []byte("CloudGeek"), 0666) if err != nil { fmt.Println(err) } }
func main() { //目录遍历 files, err := ioutil.ReadDir("d:\\d") if err != nil { fmt.Println(err) } else { for _, file := range files { fmt.Println("文件名:", file.Name(), "文件大小:", file.Size()) } } }
func main() { //file是os.File类型,实现了io.Reader接口 file, err := os.Open("d:\\d\\1.txt") if err != nil { fmt.Println(err) } else { //ReadAll方法接收io.Reader类型的参数,返回一个[]byte类型的结果 b, err := ioutil.ReadAll(file) if err != nil { fmt.Println(err) } else { //[]byte类型的数据转换为string后输出 fmt.Println(string(b)) } } }
bufio 包实现了带缓存的 I/O 操作,封装了io.Writer和io.Reader类型
func main() { //创建文件(忽略错误处理过程) file, _ := os.Create("d:\\d\\1.txt") defer file.Close() //写入2个字符串到缓存区 w := bufio.NewWriter(file) n1, _ := w.WriteString("CloudGeek!") n2, _ := w.WriteString("CloudGeek!") //将缓存中内容写到文件 w.Flush() fmt.Println(n1, n2) }
这个例子中bufio.NewWriter返回的是bufio.Writer类型,这个类型封装了io.Writer,增加了buf等字段来支持缓存操作,定义如下:
先看一个及其简单的读取单个字符串输入的例子:
func main() { var username string fmt.Scanln(&username) fmt.Println("username is:", username) }
在这个例子中,在控制台输入CloudGeek,得到的输出结果是:username is: CloudGeek
Scanln读取到换行或者EOF就会结束,中间读取到的字符串不能包含空格,不然就处理为多个字符串,这个例子中只用了一个username变量接收,所以如果输入:cloud geek,就只能获取到cloud。Scanln方法是从os.Stdin读取数据,Stdin是什么呢?如下:
NewFile的返回值是*File类型的变量,File类型实现了io.Writer和io.Reader接口,所以又和开始介绍的io包对应起来了。
本文主要带你了解golang中的IO,最主要是掌握io接口Writer和Reader,知道这个的基础上,在具体应用的时候无论是用到文件操作,缓存处理,终端输入输出等哪一块,再去查查相关用法的时候应该容易理解的多!
如对本文有疑问, 点击进行留言回复!!
VSCode1.4 搭建Golang的开发调试环境(遇到很多问题)
网友评论