跳转至

os.Create

编程语言中起名字还真是一个艺术,就连 golang 这么大的项目都是这样,如果光是看名字一定没有人会想到 os.Create 还会有清空当前文件的功能吧。名字起的不好只能通过文档来补充了,官方文件这样写到。

Create creates or truncates the named file. If the file already exists, it is truncated. If the file does not exist, it is created with mode 0666 (before umask). If successful, methods on the returned File can be used for I/O; the associated file descriptor has mode O_RDWR. If there is an error, it will be of type *PathError.

明确系统调用

操作系统提供的 creat 是没有 trucate 这个功能的,它的 C 语言声明如下

include <fentl.h>
int creat (const char *path, mode_t mode);
可以看出 golang 这个 os.Create 并不是直接绑定的 creat 系统调用,那它后面对应的是哪个(哪几个)系统调用呢?只能写一下程序 trace 下了。

package main

import (
    "log"
    "os"
    "fmt"
)

var (
    newFile *os.File
    err     error
)

func main() {
    fmt.Println("begin-to-call os.Create")
    newFile, err = os.Create("test.txt")
    fmt.Println("end-to-call os.Create")
    if err != nil {
        log.Fatal(err)
    }
    log.Println(newFile)
    newFile.Close()

运行效果

go build -o main main.go
strace ./main 


write(1, "begin-to-call os.Create\n", 24begin-to-call os.Create) = 24

openat(AT_FDCWD, "test.txt", O_RDWR|O_CREAT|O_TRUNC|O_CLOEXEC, 0666) = 3

... ...
write(1, "end-to-call os.Create\n", 22end-to-call os.Create) = 22
可以看到 os.Create 背后是 openat 这个系统调用,O_CREAT|O_TRUNC 这两个 flag 会告诉操作系统,如果文件存在就 trucate 它,如果不存在就创建一个新的文件;这么一通操作下目标文件一定是空文件了。


open相关的两个系统调用

#include <fentl.h>
int open(const char spath, int oflag, ... /* mode_t mode */);
int openat(int fd, const char *path, int oflag, .../* mode_t mode */);