当前位置: 移动技术网 > IT编程>脚本编程>Go语言 > CloudGeek讲golang系列 - golang中的io操作

CloudGeek讲golang系列 - golang中的io操作

2018年06月09日  | 移动技术网IT编程  | 我要评论

0、写在最前面

这篇文章讲什么?不讲什么?

我会从什么是io操作开始,逐步展开golang中的io知识体系;这个过程不会去按顺序介绍io包的所有接口啥的,那样做看似全面,其实很枯燥,看完就是忘完。如果你对IO操作有基础的认识,但是不知道golang中的io是怎么回事,那么下面的介绍会帮助你轻松入门了解io in go!

一、何为IO操作

 io操作简单理解就是从某处读/写到某处;比如读取键盘输入,读取文件,输出到终端,输出到一个文件……

二、golang中的io包

go语言的io 包提供了I/O原语的基本接口,我们先看最最基础的2个接口

  • io.Reader
  • io.Writer

如上所示,2个接口的定义很简单,都只包含一个方法,下面分别介绍

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

  • Read方法有一个[]byte类型的参数p,p相当于存放读取到的数据流的载体,p的长度可以大于实际接收到的数据,也就是容量为10的p可以只存放大小为5的数据,没有要求放满。
  • 当 Read 在成功读取 n > 0 个字节后遇到一个错误或EOF,它就会返回读取的字节数,此时err是nil或者EOF。

Read的用法应该还是容易理解,就是用一个p来暂存读取到的数据。任意一个类型只要实现了Read方法就算实现了Reader接口,也就成为了Reader接口的一个实例。如果暂时没有完全理解,等后面看完具体的用例再回过头来看看Read方法吧~

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

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接口的那些类型是怎么工作的

三、golang中的文件io

1、os.File

 先看源码中怎么定义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操作,参数列表和返回值含义都是和前面介绍接口的时候讲的一样。

2、io/ioutil

  •  例子一:读取整个文件
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())
		}
	}
}
  • 例子四:读取任意实现了io.Reader接口的数据到一个[]byte中
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))
		}
	}
}

3、bufio

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等字段来支持缓存操作,定义如下:

四、golang中读取用户键盘输入

 先看一个及其简单的读取单个字符串输入的例子:

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,知道这个的基础上,在具体应用的时候无论是用到文件操作,缓存处理,终端输入输出等哪一块,再去查查相关用法的时候应该容易理解的多!

如对本文有疑问, 点击进行留言回复!!

相关文章:

验证码:
移动技术网