输入输出
io-基本的IO接口
io包为I/O原语提供了基本的接口。包装了原语的已有实现。
只要满足Reader和Writer接口,就可以使用IO包的功能。
Reader接口
定义:
1 | type Reader interface { |
Read将len(p)个字节读取到p中。返回读取的字节数n和遇到的错误。
Reader接口的方法集只包含了一个Read方法,所有实现了Read方法的类型都可以满足io.Reader接口。
1 | func ReadFrom(reader io.Reader, num int) ([]byte, error) { |
传递的参数是个接口,在函数中调用了这个接口变量的Read方法,只需要在向ReadFrom函数传递实参的时候传递一个实现了该接口的对象,这样就把对象赋值给了接口。
Writer 接口
定义:
1 | type Write interface { |
所有实现了Write方法的类型都实现了 io.Writer 接口。
实现了io.Reader接口或io.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
- encoding/csv.Reader/Writer 分别实现了 io.Reader 和 io.Writer
- net/conn 分别实现了 io.Reader 和 io.Writer(Conn接口定义了Read/Write)
常用的类型有:os.File、strings.Reader、bufio.Reader/Writer、bytes.Buffer、bytes.Reader
Go 中接口的命名约定:接口名以 er 结尾。
ReaderAt 和 WriterAt 接口
ReaderAt 接口的定义:
1 | type ReaderAt interface { |
ReadAt 从基本输入源的偏移量 off 处开始,将 len(p) 个字节读取到 p 中。它返回读取的字节数 n(0 <= n <= len(p))以及任何遇到的错误。
1 | reader := strings.NewReader("Go语言中文网") |
WriterAt 接口的定义:
1 | type WriterAt interface { |
WriteAt 从 p 中将 len(p) 个字节写入到偏移量 off 处的基本数据流中。它返回从 p 中被写入的字节数 n(0 <= n <= len(p))以及任何遇到的引起写入提前停止的错误。
1 | file, err := os.Create("writeAt.txt") |
ReaderFrom 和 WriterTo 接口
ReaderFrom 的定义:
1 | type ReaderFrom interface { |
ReadFrom 从 r 中读取数据,直到 EOF 或发生错误。其返回值 n 为读取的字节数。
1 | file, err := os.Open("writeAt.txt") |
WriterTo的定义:
1 | type WriterTo interface { |
WriteTo 将数据写入 w 中,直到没有数据可写或发生错误。其返回值 n 为写入的字节数。
1 | reader := bytes.NewReader([]byte("Go语言中文网")) |
ioutil — 方便的IO操作函数集
ReadAll 函数
Go 提供了 ReadAll 这个函数,用来从io.Reader 中一次读取所有数据。
1 | func ReadAll(r io.Reader) ([]byte, error) |
它是通过 bytes.Buffer 中的 ReadFrom 来实现读取所有数据的。
ReadDri 函数
读取目录并返回排好序的文件和子目录名( []os.FileInfo )。
1 | fileInfos, err := ioutil.ReadDir(path) |
ReadFile 和 WriteFile 函数
ReadFile 读取整个文件的内容。
ReadFile 的实现和ReadAll 类似,不过,ReadFile 会先判断文件的大小,给 bytes.Buffer 一个预定义容量,避免额外分配内存。
1 | func ReadFile(filename string) ([]byte, error) |
ReadFile 从 filename 指定的文件中读取数据并返回文件的内容。
WriteFile 函数:
1 | func WriteFile(filename string, data []byte, perm os.FileMode) error |
WriteFile 将data写入filename文件中,当文件不存在时会根据perm指定的权限进行创建一个,文件存在时会先清空文件内容。
TempDir 和 TempFile 函数
TempDir 创建临时目录。
1 | b.work, err = ioutil.TempDir("", "go-build") |
第一个参数如果为空,表明在系统默认的临时目录( os.TempDir )中创建临时目录;第二个参数指定临时目录名的前缀,该函数返回临时目录的路径。
TempFile 用于创建临时文件。
1 | f1, err := ioutil.TempFile("", "gofmt") |
第一个参数如果为空,表明在系统默认的临时目录( os.TempDir )中创建临时文件;第二个参数指定临时文件名的前缀,该函数返回临时文件的路径。
创建者创建的临时文件和临时目录要负责删除这些临时目录和文件。
如删除临时文件:
1 | defer func() { |
fmt — 格式化IO
Printing
Sample
1 | type user struct { |
占位符
占位符 | 说明 |
---|---|
%v | 相应值的默认格式。“加号”标记(%+v)会添加字段名 |
%#v | 相应值的Go语法表示 |
%T | 相应值的类型的Go语法表示 |
%% | 字面上的百分号,并非值的占位符 |
%t | true 或 false。 |
%b | 二进制表示 |
%c | 相应Unicode码点所表示的字符 |
%d | 十进制表示 |
%o | 八进制表示 |
%q | 单引号围绕的字符字面值,由Go语法安全地转义 |
%x | 十六进制表示,字母形式为小写 a-f |
%X | 十六进制表示,字母形式为大写 A-F |
%s | 输出字符串表示(string类型或[]byte) |
%p | 十六进制表示,前缀 0x |
%f | 有小数点而无指数,例如 123.456 |
%e | 科学计数法,例如 -1234.456e+78 |
%g | 根据情况选择 %e 或 %f 以产生更紧凑的(无末尾的0)输出 |
%G | 根据情况选择 %E 或 %f 以产生更紧凑的(无末尾的0)输出 |
%E | 科学计数法,例如 -1234.456E+78 |
对数值而言,宽度为该数值占用区域的最小宽度;精度为小数点之后的位数。
Scanning
Scan、Scanf 和 Scanln 从 os.Stdin 中读取; Fscan、Fscanf 和 Fscanln 从指定的 io.Reader 中读取; Sscan、Sscanf 和 Sscanln 从实参字符串中读取。
Scanf、Fscanf 和 Sscanf 需要输入换行符来匹配格式中的换行符;其它函数则将换行符视为空格。
Scanf、Fscanf 和 Sscanf 根据格式字符串解析实参。
宽度被解释为输入的文本(%5s 意为最多从输入中读取5个 rune 来扫描成字符串),而扫描函数则没有精度的语法(没有 %5.2f,只有 %5f)。
Print 序列函数
Fprint/Fprintf/Fprintln 函数的第一个参数接收一个io.Writer类型,会将内容输出到 io.Writer 中去。
Print/Printf/Println 函数是将内容输出到标准输出中。
Sprint/Sprintf/Sprintln 是格式化内容为 string 类型,而并不输出到某处,需要格式化字符串并返回时。
Scan 序列函数
Fscan/Fscanf/Fscanln 函数的第一个参数接收一个 io.Reader 类型,从其读取内容并赋值给相应的实参。
Scan/Scanf/Scanln 正是从标准输入获取内容。
Sscan/Sscanf/Sscanln 则直接从字符串中获取内容。
bufio — 缓存IO
Reader 类型和方法
bufio.Reader 结构包装了一个 io.Reader 对象,提供缓存功能,同时实现了 io.Reader 接口。
1 | type Reader struct { |
实列化
bufio 包提供了两个实例化 bufio.Reader 对象的函数:NewReader 和 NewReaderSize。其中,NewReader 函数是调用 NewReaderSize 函数实现的:
1 | func NewReader(rd io.Reader) *Reader { |
NewReaderSize的源码:
1 | func NewReaderSize(rd io.Reader, size int) *Reader { |