1. 概述
os
包提供了操作系统函数的不依赖平台的接口。失败的调用会返回错误值而非错误码。通常错误值里包含更多信息。例如,如果某个使用一个文件名的调用(如Open、Stat)失败了,打印错误时会包含该文件名,错误类型将为 *PathError
,其内部可以解包获得更多信息。
type PathError struct {Op stringPath stringErr error
}
PathError
记录一个错误,以及导致错误的路径。
func (e *PathError) Error() string
2. type FileInfo
type FileInfo interface {Name() string // 文件的名字(不含扩展名)Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同Mode() FileMode // 文件的模式位ModTime() time.Time // 文件的修改时间IsDir() bool // 等价于Mode().IsDir()Sys() interface{} // 底层数据来源(可以返回nil)
}
FileInfo
用来描述一个文件对象。
func Stat(name string) (fi FileInfo, err error)
Stat
返回一个描述 name
指定的文件对象的 FileInfo
。如果指定的文件对象是一个符号链接,返回的 FileInfo
描述该符号链接指向的文件的信息,本函数会尝试跳转该链接。如果出错,返回的错误值为 *PathError
类型。
代码示例:
package mainimport ("fmt""os"
)func main() {// Stat 返回一个描述 name 指定的文件对象的 FileInfofi, err := os.Stat("./test.txt")if err != nil {fmt.Println(err)}fileName := fi.Name()fileSize := fi.Size()fileMode := fi.Mode()fileModTime := fi.ModTime()isDir := fi.IsDir()fileSys := fi.Sys()fmt.Printf("fileName is %#v\n", fileName)fmt.Printf("fileSize is %#v\n", fileSize)fmt.Printf("fileMode is %#v\n", fileMode)fmt.Printf("fileModTime is %#v\n", fileModTime)fmt.Printf("isDir is %#v\n", isDir)fmt.Printf("fileSys is %#v\n", fileSys)
}
3. type FileMode
FileModel
的方法主要用来进行判断和输出权限。
type FileMode uint32
FileMode
代表文件的模式和权限位。这些字位在所有的操作系统都有相同的含义,因此文件的信息可以在不同的操作系统之间安全的移植。不是所有的位都能用于所有的系统,唯一共有的是用于表示目录的 ModeDir
位。
函数定义 | 函数说明 |
---|---|
func (m FileMode) IsDir() bool | IsDir报告m是否是一个目录 |
func (m FileMode) IsRegular() bool | IsRegular报告m是否是一个普通文件 |
func (m FileMode) Perm() FileMode | Perm方法返回m的Unix权限位 |
func (m FileMode) String() string | 返回m的字符串表示 |
使用示例:
func main() {// Stat 返回一个描述 name 指定的文件对象的 FileInfofi, err := os.Stat("./test.log")if err != nil {fmt.Println(err)}fm := fi.Mode() // 返回 FileMode fmt.Println(fm.IsDir()) // falsefmt.Println(fm.IsRegular()) // truefmt.Println(fm.Perm()) // -rw-rw----fmt.Println(fm.String()) // -rw-rw----
}
实际文件显示:
wohu@wohu:~/GoCode/src/task$ ll
total 20
-rw-rw-r-- 1 wohu wohu 250 5月 20 09:40 main.go
-rw-rw---- 1 wohu wohu 0 5月 15 10:54 test.log
4. 主要函数
4.1 os.Hostname、Exit、Getpid、Getppid、
函数定义 | 函数说明 |
---|---|
func Hostname() (name string, err error) | Hostname返回内核提供的主机名。 |
func Environ() []string | Environ返回表示环境变量的格式为"key=value"的字符串的切片拷贝 |
func ExpandEnv(s string) string | 根据当前环境变量的值替换字符串中的 ${var} 或 $var。对未定义变量的引用将被空字符串替换 |
func Getenv(key string) string | Getenv检索并返回名为key的环境变量的值。如果不存在该环境变量会返回空字符串,要区分空值和未设置值,请使用 LookupEnv |
func LookupEnv(key string) (string, bool) | 检索 key 这个键对应的环境变量的值,如果该环境变量存在,则返回对应的值(可能为空),并且布尔值为 true,否则,返回值将为空,布尔值将为 false |
func Setenv(key, value string) error | Setenv设置名为key的环境变量。如果出错会返回该错误 |
func Unsetenv(key string) error | 取消设置单个环境变量 |
func Clearenv() | Clearenv删除所有环境变量(谨慎使用) |
func Exit(code int) | Exit让当前程序以给出的状态码code退出。一般来说,状态码0表示成功,非0表示出错。 程序会立刻终止,defer的函数不会被执行 |
func Getuid() int | Getuid返回调用者的用户ID |
func Geteuid() int | Geteuid返回调用者的有效用户ID |
func Getgid() int | Getgid返回调用者的组ID |
func Getegid() int | Getegid返回调用者的有效组ID |
func Getgroups() ([]int, error) | Getgroups返回调用者所属的所有用户组的组ID |
func Getpid() int | Getpid返回调用者所在进程的进程ID |
func Getppid() int | Getppid返回调用者所在进程的父进程的进程ID |
使用示例:
func main() {hostname, err := os.Hostname()if err != nil {fmt.Println(err)}env := os.Environ()goroot := os.Getenv("GOROOT")name := os.Getenv("NAME")fmt.Println("name is:", name)pid := os.Getpid()ppid := os.Getppid()os.Exit(0)fmt.Println(hostname)fmt.Println(env)fmt.Println(goroot)fmt.Println(pid)fmt.Println(ppid)
}
执行:
$ NAME=wohu go run main.go
name is: wohu
示例
host := os.ExpandEnv("127.0.0.1:$PORT")
fmt.Println(host)
它会将 $PORT
替换为 os.Getenv("PORT")
的值。
4.2 os.IsExist
func IsExist(err error) bool
返回一个布尔值说明该错误是否表示一个文件或目录已经存在。 ErrExist
和一些系统调用错误会使它返回真。
4.3 os.IsNotExist
func IsNotExist(err error) bool
返回一个布尔值说明该错误是否表示一个文件或目录不存在。 ErrNotExist
和一些系统调用错误会使它返回真。
4.4 os.IsPermission
func IsPermission(err error) bool
返回一个布尔值说明该错误是否表示因权限不足要求被拒绝。 ErrPermission
和一些系统调用错误会使它返回真
4.5 os.Getwd
func Getwd() (dir string, err error)
返回一个对应当前工作目录的根路径。如果当前目录可以经过多条路径抵达(因为硬链接), Getwd
会返回其中一个。
4.5 os.Chdir
func Chdir(dir string) error
将当前工作目录修改为 dir
指定的目录。如果出错,会返回 *PathError
底层类型的错误。
代码示例如下:
func main() {_, err := os.Stat("./test.log")if os.IsExist(err) {fmt.Println("test.log do not exist")}if os.IsNotExist(err) {fmt.Println("test.log exist")}curDir, err := os.Getwd()if err != nil {fmt.Println(err)}fmt.Println(curDir) // /home/wohu/GoCode/src/taskerr = os.Chdir("/opt/")if err != nil {fmt.Println(err)}chDir, err := os.Getwd()if err != nil {fmt.Println(err)}fmt.Println(chDir) // opt
}
4.6 os.Chmod
func Chmod(name string, mode FileMode) error
修改 name
指定的文件对象的 mode
。如果 name
指定的文件是一个符号链接,它会修改该链接的目的地文件的 mode
。如果出错,会返回 *PathError
底层类型的错误。
代码示例:
func main() {// Stat 返回一个描述 name 指定的文件对象的 FileInfofi, err := os.Stat("./test.log")if err != nil {fmt.Println(err)}fm := fi.Mode() // 返回 FileModefilePerm := fm.Perm()fmt.Println(filePerm) // 修改前权限为 -rw-rw----err = os.Chmod("./test.log", 0755)if err != nil {fmt.Println(err)}fi, err = os.Stat("./test.log")if err != nil {fmt.Println(err)}filePerm = fm.Perm()fmt.Println(filePerm) // 修改后权限为 -rwxr-xr-x
}
4.7 os.Chown
func Chown(name string, uid, gid int) error
修改 name
指定的文件对象的用户 id
和组 id
。如果 name
指定的文件是一个符号链接,它会修改该链接的目的地文件的用户 id
和组 id
。如果出错,会返回 *PathError
底层类型的错误。
4.8 os.Getgroups
func Getgroups() ([]int, error)
返回调用者属于的 group
,其和 chown
配合使用,改变文件属于的 group
。
代码示例:
func main() {fmt.Println(os.Getgroups()) //获取调用者属于的组 [4 24 27 30 46 108 124 1000]fmt.Println(os.Getgid()) //获取调用者当前所在的组 1000fmt.Println(os.Chown("tmp.txt", 1000, 46)) //更改文件所在的组
}
4.9 os.Mkdir
func Mkdir(name string, perm FileMode) error
使用指定的权限和名称创建一个目录,仅适用于创建父目录存在且要创建的目录不存在的情况。如果要创建的目录已经存在,则会报错,如果出错,会返回 *PathError
底层类型的错误。
4.10 os.MkdirAll
func MkdirAll(path string, perm FileMode) error
使用指定的权限和名称创建一个目录,包括任何必要的上级目录,并返回 nil
,否则返回错误。权限位 perm
会应用在每一个被本函数创建的目录上。如果 path
指定了一个已经存在的目录, MkdirAll
不做任何操作并返回 nil
。
代码示例:
func main() {errMsg := os.Mkdir("./testDir", 0775)if errMsg != nil {fmt.Println("创建目录失败", errMsg)return}errMsg2 := os.MkdirAll("./a/b", 0775)if errMsg2 != nil {fmt.Println("创建目录失败", errMsg2)return}
}
4.11 os.Rename
func Rename(oldpath, newpath string) error
修改一个文件的名字,移动一个文件。可能会有一些个操作系统特定的限制。
4.12 os.Remove
func Remove(name string) error
删除 name
指定的文件或目录。如果是目录的话必须要求该目录为空才能删除,否则会报错,会返回 *PathError
底层类型的错误。
4.13 os.RemoveAll
func RemoveAll(path string) error
删除 path
指定的文件,或目录及它包含的任何下级对象。它会尝试删除所有东西,除非遇到错误并返回。如果 path
指定的对象不存在, RemoveAll
会返回 nil
而不返回错误。
示例代码如下:
func main() {err := os.Rename("a", "b")if err != nil {fmt.Println(err)}err = os.Remove("./b")if err != nil {fmt.Println(err)}err = os.RemoveAll("./b")if err != nil {fmt.Println(err)}
}
5. type file
type File struct {// 内含隐藏或非导出字段
}
File
代表一个打开的文件对象。
5.1 返回文件对象的函数
5.1.1 os.Create
func Create(name string) (file *File, err error)
Create
采用模式 0666(任何人都可读写,不可执行)创建一个名为 name
的文件,如果文件已存在会截断它(为空文件)。如果成功,返回的文件对象可用于 I/O
;对应的文件描述符具有 O_RDWR
模式。如果出错,错误底层类型是 *PathError
。
5.1.2 os.Open
func Open(name string) (file *File, err error)
Open
打开一个文件用于读取。如果操作成功,返回的文件对象的方法可用于读取数据;对应的文件描述符具有 O_RDONLY
模式。如果出错,错误底层类型是 *PathError
。
该函数只能以只读模式打开文件。换句话说,我们只能从该函数返回的File值中读取内容,而不能向它写入任何内容。
5.1.3 os.OpenFile
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)
OpenFile
是一个更一般性的文件打开函数,大多数调用者都应用 Open
或 Create
代替本函数。它会使用指定的选项(如 O_RDONLY
等)、指定的模式(如 0666
等)打开指定名称的文件。如果操作成功,返回的文件对象可用于 I/O
。如果出错,错误底层类型是 *PathError
。
这个函数其实是 os.Create
函数和 os.Open
函数的底层支持,它最为灵活。这个函数有 3 个参数,分别名为 name
、flag
和 perm
。其中的 name
指代的就是文件的路径。而 flag
参数指的则是需要施加在文件描述符之上的模式,我在前面提到的只读模式就是这里的一个可选项。在 Go
语言中,这个只读模式由常量 os.O_RDONLY
代表,它是 int
类型的。当然了,这里除了只读模式之外,还有几个别的模式可选。
5.1.4 os.NewFile
func NewFile(fd uintptr, name string) *File
NewFile
使用给出的 Unix
文件描述符和名称创建一个文件。该函数在被调用的时候,需要接受一个代表文件描述符的、uintptr
类型的值,以及一个用于表示文件名的字符串值。
注意,不要被这个函数的名称误导了,它的功能并不是创建一个新的文件,而是依据一个已经存在的文件的描述符,来新建一个包装了该文件的 File
值。
eg:像这样拿到一个包装了标准错误输出的 File
值。
file3 := os.NewFile(uintptr(syscall.Stderr), "/dev/stderr")if file3 != nil {defer file3.Close()file3.WriteString("The Go language program writes the contents into stderr.\n")
}
图片来源: https://time.geekbang.org/column/article/68779
5.2 文件对象的方法
func (f *File) Name() string
Name
方法返回(提供给 Open/Create
等方法的)文件名称。
func (f *File) Stat() (fi FileInfo, err error)
Stat
返回描述文件 f
的 FileInfo
类型值。如果出错,错误底层类型是 *PathError
。
func (f *File) Fd() uintptr
Fd
返回与文件 f
对应的整数类型的 Unix
文件描述符。
func (f *File) Chdir() error
Chdir
将当前工作目录修改为 f
, f
必须是一个目录。如果出错,错误底层类型是 *PathError
。
func (f *File) Chmod(mode FileMode) error
Chmod
修改文件的模式。如果出错,错误底层类型是 *PathError
。
func (f *File) Chown(uid, gid int) error
Chown
修改文件的用户 ID
和组 ID
。如果出错,错误底层类型是 *PathError
。
func (f *File) Readdir(n int) (fi []FileInfo, err error)
Readdir
读取目录 f
的内容,返回一个有 n
个成员的 []FileInfo
,这些 FileInfo
是被 Lstat
返回的,采用目录顺序。对本函数的下一次调用会返回上一次调用剩余未读取的内容的信息。
如果 n>0
, Readdir
函数会返回一个最多 n
个成员的切片。这时,如果 Readdir
返回一个空切片,它会返回一个非 nil
的错误说明原因。如果到达了目录 f
的结尾,返回值 err
会是 io.EOF
。
如果 n<=0
, Readdir
函数返回目录中剩余所有文件对象的 FileInfo
构成的切片。此时,如果 Readdir
调用成功(读取所有内容直到结尾),它会返回该切片和 nil
的错误值。如果在到达结尾前遇到错误,会返回之前成功读取的 FileInfo
构成的切片和该错误。
func (f *File) Readdirnames(n int) (names []string, err error)
Readdirnames
读取并返回目录 f
里面的文件的名字切片。
如果 n>0
, Readdirnames
返回最多 n
个名字。在这种情况下,如果 Readdirnames
返回一个空的切片,它会返回一个非空的错误来解释原因。在目录的结尾,错误为 EOF
。
如果 n<0
, Readdirnames
返回目录下所有的文件的名字,用一个切片表示。在这种情况下,如果用一个切片表示成功(读取直到目录结尾),它返回切片和一个空的错误。如果在目录结尾之前遇到了一个错误, Readdirnames
返回直到当前所读到的 names
和一个非空的错误。
func (f *File) Truncate(size int64) error
Truncate
改变文件的大小,它不会改变 I/O
的当前位置。 如果截断文件,多出的部分就会被丢弃。如果出错,错误底层类型是 *PathError
。
func (f *File) Read(b []byte) (n int, err error)
Read
方法从 f
中读取最多 len(b)
字节数据并写入 b
。它返回读取的字节数和可能遇到的任何错误。文件终止标志是读取 0 个字节且返回值 err
为 io.EOF
。
func (f *File) ReadAt(b []byte, off int64) (n int, err error)
ReadAt
从指定的位置(相对于文件开始位置)读取 len(b)
字节数据并写入 b
。它返回读取的字节数和可能遇到的任何错误。当 n<len(b)
时,本方法总是会返回错误;如果是因为到达文件结尾,返回值 err
会是 io.EOF
。
func (f *File) Write(b []byte) (n int, err error)
Write
向文件中写入 len(b)
字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值 n!=len(b)
,本方法会返回一个非 nil
的错误。
func (f *File) WriteString(s string) (ret int, err error)
WriteString
类似 Write
,但接受一个字符串参数。
func (f *File) WriteAt(b []byte, off int64) (n int, err error)
WriteAt
在指定的位置(相对于文件开始位置)写入 len(b)
字节数据。它返回写入的字节数和可能遇到的任何错误。如果返回值 n!=len(b)
,本方法会返回一个非 nil
的错误。
func (f *File) Seek(offset int64, whence int) (ret int64, err error)
Seek
设置下一次读/写的位置。
6. 用于File值的操作模式
针对 File
值的操作模式主要有只读模式、只写模式和读写模式。这些模式分别由常量 os.O_RDONLY
、os.O_WRONLY
和 os.O_RDWR
代表。
在我们新建或打开一个文件的时候,必须把这三个模式中的一个设定为此文件的操作模式。除此之外,我们还可以为这里的文件设置额外的操作模式,可选项如下所示。
os.O_APPEND
当向文件中写入内容时,把新内容追加到现有内容的后边。os.O_CREATE
当给定路径上的文件不存在时,创建一个新文件。os.O_EXCL
需要与os.O_CREATE
一同使用,表示在给定的路径上不能有已存在的文件。os.O_SYNC
在打开的文件之上实施同步I/O
。它会保证读写的内容总会与硬盘上的数据保持同步。os.O_TRUNC
如果文件已存在,并且是常规的文件,那么就先清空其中已经存在的任何内容。
对于以上操作模式的使用,os.Create
函数和 os.Open
函数都是现成的例子。
func Create(name string) (*File, error) { return OpenFile(name, O_RDWR|O_CREATE|O_TRUNC, 0666)
}
os.Create
函数在调用 os.OpenFile
函数的时候,给予的操作模式是 os.O_RDWR
、os.O_CREATE
和 os.O_TRUNC
的组合。
这就基本上决定了前者的行为,即:如果参数 name
代表路径之上的文件不存在,那么就新建一个,否则,先清空现存文件中的全部内容。并且,它返回的 File
值的读取方法和写入方法都是可用的。
这里需要注意,多个操作模式是通过按位或操作符|组合起来的。
func Open(name string) (*File, error) {return OpenFile(name, O_RDONLY, 0)
}
os.Open
函数的功能是:以只读模式打开已经存在的文件。其根源就是它在调用 os.OpenFile
函数的时候,只提供了一个单一的操作模式 os.O_RDONLY
。
7. 设定常规文件的访问权限
我们已经知道,os.OpenFile
函数的第三个参数 perm
代表的是权限模式,其类型是 os.FileMode
。
但实际上,os.FileMode
类型能够代表的,可远不只权限模式,它还可以代表文件模式(也可以称之为文件种类)。
由于 os.FileMode
是基于 uint32
类型的再定义类型,所以它的每个值都包含了 32 个比特位。在这 32 个比特位当中,每个比特位都有其特定的含义。
比如,如果在其最高比特位上的二进制数是1,那么该值表示的文件模式就等同于 os.ModeDir
,也就是说,相应的文件代表的是一个目录。又比如,如果其中的第 26 个比特位上的是1,那么相应的值表示的文件模式就等同于 os.ModeNamedPipe
,也就是说,那个文件代表的是一个命名管道。
实际上,在一个 os.FileMode
类型的值(以下简称 FileMode
值)中,只有最低的 9 个比特位才用于表示文件的权限。当我们拿到一个此类型的值时,可以把它和 os.ModePerm
常量的值做按位与操作。这个常量的值是0777,是一个八进制的无符号整数,其最低的 9 个比特位上都是1,而更高的 23 个比特位上都是0。所以,经过这样的按位与操作之后,我们即可得到这个 FileMode
值中所有用于表示文件权限的比特位,也就是该值所表示的权限模式。
这将会与我们调用 FileMode
值的 Perm
方法所得到的结果值是一致。在这 9 个用于表示文件权限的比特位中,每 3 个比特位为一组,共可分为 3 组。从高到低,这 3 组分别表示的是文件所有者(也就是创建这个文件的那个用户)、文件所有者所属的用户组,以及其他用户对该文件的访问权限。而对于每个组,其中的 3 个比特位从高到低分别表示读权限、写权限和执行权限。如果在其中的某个比特位上的是1,那么就意味着相应的权限开启,否则,就表示相应的权限关闭。
因此,八进制整数 0777 就表示:操作系统中的所有用户都对当前的文件有读、写和执行的权限,而八进制整数 0666 则表示:所有用户都对当前文件有读和写的权限,但都没有执行的权限。我们在调用 os.OpenFile
函数的时候,可以根据以上说明设置它的第三个参数。
但要注意,只有在新建文件的时候,这里的第三个参数值才是有效的。在其他情况下,即使我们设置了此参数,也不会对目标文件产生任何的影响。
8. os 中关于进程的操作
参考:
https://studygolang.com/pkgdoc
https://www.cnblogs.com/sunailong/p/7554013.html
https://blog.csdn.net/weiyuefei/article/details/77892871