go语言的os库

go语言的类库众多,而且资料不是很多,go语言的官方文档(地址:http://golang.org/doc/articles/wiki/)例子也 不多,读起来很是费劲。我翻过很多在网上对go各种库的评论,褒贬不一,但是我觉得go语言的库使用起来还是很 方便的。这里我们在进入OS库之前介绍一下flag库。

flag

flag包是用来处理go语言的命令行参数的,其实go的参数很容易得到,os.Args就是其参数数组。但是我们怎么从 形如main.go -p 80 -h localhost这样的命令行中读出参数呢,看下面的例子:

var s int
host := flag.String("host", "zhing.github.com", "hostname")
port := flag.Int("port", 80, "a port number")
flag.IntVar(&s, "debug", 43, "some words")

flag.Parse()

fmt.Println("host:", *host)
fmt.Println("port:", *port)
fmt.Println("debug:", s)

拿第三行来解释:“port”是参数名,80是默认值,“a port number”是说明。第四行是我们拿已存在的变量来接收 参数,这样理解起来很容易明白。

os

os库几乎是go语言中信息量最大的库了,我们以函数的形式来列出其中一些:

func Getwd() (pwd string, err error)       得到当前目录pwd
func Getenv(key string) string             得到指定的环境变量
func Chdir(dir string) error               将工作目录切换至dir
func Stat(name string) (fi FileInfo, err error)  输出文件信息
func Chmod(name string, mode FileMode) error     改变文件的属性

这几个函数都是针对环境和文件来说的,对于Get*类型的函数还有很多,文档中可以方便地查到。上面的文件信息 结构FileInfo是一个接口,其构造如下:

type FileInfo interface {
    Name() string       // 文件的名称
    Size() int64        // 唱过文件的大小
    Mode() FileMode     // 文件的权限
    ModTime() time.Time // 时间
    IsDir() bool        // 是否是目录
    Sys() interface{}   // 基础数据源接口(can return nil)
}


func Environ() []string                  返回环境变量的[]string切片
func Exit(code int)                      以指定的退出码中断函数
func Expand(s string, mapping func(string) string) string 将s字符串按照mapping规则替换,返回替换后的string
func ExpandEnv(s string) string          将字符串替换成当前环境变量的内容

可能一开始替换的概念不要理解,我们来看一个例子:

mapping := func(s string) string {
    m := map[string]string{"China": "beijing"}
    return m[s]
}
data := "Pairs $China"
fmt.Println(os.Expand(data, mapping))

上例中我们将data中的China替换成beijing,这样我们可以猜到os.ExpandEnv()能够将“$GOROOT”替换成环境变量路径

func IsExist(err error) bool             对error进行解析(文件存在与否),与IsNotExist()相反
func IsPathSeparator(c uint8) bool       c是否是系统分割符
unc IsPermission(err error) bool         分析error,是否是权限不够
func Mkdir(name string, perm FileMode) error   生成目录,多级目录用MkdirAll(perm可以为os.ModePerm)
func Readlink(name string) (string, error)     读取链接文件,返回目标文件信息
func Remove(name string) error                 删除目录,多级删除用RemoveAll
func Rename(oldname, newname string) error     文件更名
func SameFile(fi1, fi2 FileInfo) bool          判断两个文件是否相同
func Setenv(key, value string) error           设置环境变量
func Symlink(oldname, newname string) error    创建软连接
func TempDir() string                          返回本地的tmp目录

我们来看看文件操作的一系列api:

func Create(name string) (file *File, err error)  创建文件,若存在则截断为0
func OpenFile(name string, flag int, perm FileMode) (file *File, err error)  指定文件权限和打开方式
func Open(name string) (file *File, err error)    打开文件
func (f *File) Name() string                      获取文件名
func (f *File) Read(b []byte) (n int, err error)  读文件,返回获取的字节数
func (f *File) ReadAt(b []byte, off int64) (n int, err error) 指定了读取的位置
func (f *File) Readdir(n int) (fi []FileInfo, err error) 读取文件夹内的文件,n为个数,0为全部
func (f *File) Readdirnames(n int) (names []string, err error) 返回文件名(与上一个略有差别)
func (f *File) Seek(offset int64, whence int) (ret int64, err error) 与c的Seek有点像
func (f *File) Write(b []byte) (n int, err error)    写入文件,返回写入的字节数
func (f *File) WriteAt(b []byte, off int64) (n int, err error)  指定了写入的位置
func (f *File) WriteString(s string) (ret int, err error)      写入字符串

上面我们将os库大致梳理了一下(当然不包括子包),上面我们需要注意的是区分文件指针(*File)和文件信息结构 (FileInfo),然后灵活运用,达到看到函数原型就知道该如何运用的境地。

除了和文件、环境变量关系密切外还和进程Process相关,下面是几个函数:

func FindProcess(pid int) (p *Process, err error)   找到进程号为pid的进程
func StartProcess(name string, argv []string, attr *ProcAttr) (*Process, error) 一个低级的启动进程接口
func (p *Process) Kill() error                      杀死进程

os/exec

一看这个包名就知道跟进程和命令的执行有关,os包中也有一些跟process有关的函数,但这些都比较底层,用起来 比较棘手。在介绍这个包之前,我们来先看一个结构:

type Cmd struct {
     Path string
     Args []string
     Env []string
     Dir string
     Stdin io.Reader
     Stdout io.Writer
     Stderr io.Writer
     ExtraFiles []*os.File
     SysProcAttr *syscall.SysProcAttr
     Process *os.Process
     ProcessState *os.ProcessState
}

结合这个结构我们再来看函数更清晰了:

func Command(name string, arg ...string) *Cmd      c=exec.Command("ls")调用的函数
func (c *Cmd) CombinedOutput() ([]byte, error)     返回标准输出和错误
func (c *Cmd) Output() ([]byte, error)             同上
func (c *Cmd) Run() error                          执行命令
func (c *Cmd) StderrPipe() (io.ReadCloser, error)  标准错误管道
func (c *Cmd) StdinPipe() (io.WriteCloser, error)  标准输入管道
func (c *Cmd) StdoutPipe() (io.ReadCloser, error)  标准输出管道
func (e *Error) Error() string                     自定义执行失败的错误信息

通过os/exec包,我们可以更好地掌控进程,特别是通过管道来控制输入输出。

os/user和os/signal

这两个包我们不大可能经常用到,如果在项目中遇到我会单独拿出来说。



Previous     Next
zhing /
Published under (CC) BY-NC-SA in categories go  tagged with go