os 包提供了平台无关的操作系统功能接口,主要是文件相关的I/O
,本文会重点对文件操作进行介绍。
文件 I/O
在 Go 中,文件描述符封装在os.File
结构中。os.File
代表一个打开的文件对象,可以使用该对象进行文件读写操作。
type File struct {
*file // os specific
}
type file struct {
pfd poll.FD
name string
dirinfo *dirInfo // nil unless directory being read
appendMode bool // whether file is opened for appending
}
打开和关闭文件 OpenFile/Open/Close
☕️ OpenFile
函数
OpenFile()
是一个一般性的文件打开函数,大多数调用都应该使用Open()
或Create()
代替本函数。它会使用指定的选项(如O_RDONLY
等)、指定的模式(如 0666 等)打开指定名称的文件。如果操作成功,返回的文件对象可用于 I/O。如果出错,错误底层类型是*PathError
。
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
此处需要特别介绍openFile()
函数参数:
-
name
:要打开的文件名,可以是一个绝对路径或相对路径,也可以是一个符号链接。 -
flag
:指定文件的访问模式,可用值已在 os 包中定义为常量。模式有以下几种:
模式 | 含义 |
---|---|
os.O_RDONLY |
只读 |
os.O_WRONLY |
只写(覆盖方式写) |
os.O_RDWR |
读写(覆盖方式写) |
os.O_APPEND |
往文件尾部追加方式写 |
os.O_CREATE |
如果文件不存在则先创建 |
os.O_EXCL |
和O_CREATE 配合使用,文件必须不存在 |
os.O_SYNC |
以同步I/O 的方式打开文件 |
os.O_TRUNC |
打开时清空文件 |
多种访问模式可以使用|
操作符来连接,例如:O_RDWR|O_CREATE|O_TRUNC
。其中,O_RDONLY
、O_WRONLY
、O_RDWR
三种模式只能指定一个。
-
perm
:指定了文件的模式和权限位,类型是os.FileMode
。
这些字位在所有的操作系统都有相同的含义,因此文件的信息可以在不同的操作系统之间安全的移植。不是所有的位都能用于所有的系统,唯一共有的是用于表示目录的ModeDir
位。
type FileMode uint32
const (
// 单字符是被 String 方法用于格式化的属性缩写。
ModeDir FileMode = 1 << (32 - 1 - iota) // d: 目录
ModeAppend // a: 只能写入,且只能写入到末尾
ModeExclusive // l: 用于执行
ModeTemporary // T: 临时文件(非备份文件)
ModeSymlink // L: 符号链接(不是快捷方式文件)
ModeDevice // D: 设备
ModeNamedPipe // p: 命名管道(FIFO)
ModeSocket // S: Unix 域 socket
ModeSetuid // u: 表示文件具有其创建者用户 id 权限
ModeSetgid // g: 表示文件具有其创建者组 id 的权限
ModeCharDevice // c: 字符设备,需已设置 ModeDevice
ModeSticky // t: 只有 root/ 创建者能删除 / 移动文件
// 覆盖所有类型位(用于通过 & 获取类型位),对普通文件,所有这些位都不应被设置
ModeType = ModeDir | ModeSymlink | ModeNamedPipe | ModeSocket | ModeDevice
ModePerm FileMode = 0777 // 覆盖所有 Unix 权限位(用于通过 & 获取类型位)
)
文件的权限打印出来一共十个字符。文件有三种基本权限:r(read,读权限)、w(write,写权限)、x(execute,执行权限),具体如下:
- rwx rw- r--
-
第 1 位:文件类型(d为目录,-为普通文件)
-
第 2-4 位:所属用户权限,用 u(user)表示
-
第 5-7 位:所属组权限,用 g(group)表示
-
第 8-10 位:其他用户权限,用 o(other)表示
文件的权限还可以用八进制表示:r 表示为 4,w 表示为 2,x 表示为 1,- 表示为 0。例如:
-
0777
:权限- rwx rwx rwx
的八进制表示,任何人都可读写,可执行 -
0666
:权限- rw- rw- rw-
的八进制表示,任何人都可读写,但不可执行
⭐️ Open 函数
// 打开一个文件只能用于读取
func Open(name string) (file *File, err error)
该函数内部实际调用openFile()
函数,源码如下:
func Open(name string) (*File, error) {
// 以 os.O_RDONLY(只读)模式打开文件
return OpenFile(name, O_RDONLY, 0)
}
✏️ Close 函数
// 关闭文件 f,使文件不能用于读写。它返回可能出现的错误
func (f *File) Close() error
close()
用于关闭一个打开的文件描述符,并将其释放回调用进程,供该进程继续使用。当进程终止时,也会自动关闭其已打开的所有文件描述符。通常情况下,我们应该主动关闭文件描述符,如果不关闭,长期运行的服务可能会把文件描述符耗尽。关于返回值 error,以下两种情况会导致Close()
返回错误:
- 关闭一个未打开的文件
- 两次关闭同一个文件
因此,通常我们不会去检查Close()
返回的错误。