概览
Go语言的标准库中,ioutil在文件和I/O操作中扮演者重要的角色。虽然从Go 1.16版本开始,Go团队认为ioutil是一个定义不清且难以理解的程序集合,所有功能的实现代码迁移至io和os包。
鉴于ioutil的功能已被标记为废弃,推荐使用新的API,本文在介绍ioutil应用时会相应介绍新的API如何使用。
新旧函数对照表
为确保代码平滑过渡,io/ioutil在Go 1.16+中通过包装新包函数实现兼容。通过阅读io/ioutil/ioutil.go和io/ioutil/tempfile.go源码,梳理出新旧版本函数对照表:
| 原函数 | 新函数 | 返回值差异 | 功能说明 |
|---|---|---|---|
| ioutil.Discard | io.Discard | 无 | |
| ioutil.NopCloser | io.NopCloser | 无 | |
| ioutil.ReadAll | io.ReadAll | 无 | |
| ioutil.ReadDir | os.ReadDir | []fs.FileInfo → []os.DirEntry | |
| ioutil.ReadFile | os.ReadFile | 无 | 读取指定文件的全部内容 |
| ioutil.TempDir | os.MkdirTemp | 无 | 读取指定目录下的文件和目录信息 |
| ioutil.TempFile | os.CreateTemp | 无 | |
| ioutil.WriteFile | os.WriteFile | 无 | 将指定数据写入指定文件 |
io/ioutil函数应用
ReadFile
在Go中,读取文件通常需要几个步骤:打开文件->读取文件->关闭文件。io/ioutil的ReadFile函数可以简化该过程,避免手动打开和关闭文件,简化了错误处理,适用于小文件。
新旧函数示例代码
go
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
var fileName = "data.txt"
data, err := ioutil.ReadFile(fileName)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
// go1.16后该功能由os.ReadFile实现,入参和返回值与旧函数保持一致
data, err = os.ReadFile(fileName)
if err != nil {
log.Fatal(err)
}
fmt.Println(string(data))
}
WriteFile
io/ioutil的WriteFile将指定数据写入指定文件,如果文件不存在则创建文件后写入,如果文件中含有内容,则会覆盖原有的内容。
新旧函数示例代码
go
package main
import (
"io/ioutil"
"log"
"os"
)
func main() {
var fileName = "data.txt"
data := []byte("Class: No.1")
err := ioutil.WriteFile(fileName, data, 0644)
if err != nil {
log.Fatal(err)
}
// go1.16后该功能由os.WriteFile实现,入参和返回值与旧函数保持一致
data = []byte("Class: No.2")
err = os.WriteFile(fileName, data, 0644)
if err != nil {
log.Fatal(err)
}
}
ReadDir
io/ioutil的ReadDir读取指定目录下所有目录和文件信息,并返回fs.FileInfo数组。新函数则是返回os.DirEntry数组
返回值结构体对比
| FileInfo | DirEntry | 说明 |
|---|---|---|
| Name() | Name() | 获取文件或者目录名 |
| IsDir() | IsDir() | 是否为文件夹 |
| Mode() | Type() | 类行位 |
| 无 | Info() | 返回FileInfo |
| Size() | 通过Info()获取FileInfo后再调用Size() |
获取文件大小 |
| ModTime() | 通过Info()获取FileInfo后再调用ModTime() |
获取文件修改时间 |
| Sys() | 通过Info()获取FileInfo后再调用Sys() |
新旧函数示例代码
go
package main
import (
"fmt"
"io/ioutil"
"log"
"os"
)
func main() {
path := "../test"
files, err := ioutil.ReadDir(path)
if err != nil {
log.Fatal(err)
}
for _, file := range files {
fmt.Println(file.Sys())
}
fmt.Println("------")
// go1.16后该功能由os.ReadDir实现,入参一致,返回值更改
newfiles, err := os.ReadDir(path)
if err != nil {
log.Fatal(err)
}
for _, file := range newfiles {
info, _ := file.Info()
fmt.Println(info.Sys())
}
}