有没有一种方法可以在设置`mtime`的同时使用`os`模块保留`atime`呢?

Is there any way to set just the mtime on a file with os.Chtimes ? I thought I could pass a modified mtime along with an unmodified atime to Chtimes, but the FileInfo returned by os.Stat only gives you mtime, via os.FileInfo.ModTime().

It seems odd that os.Chtimes requires changing both atime and mtime at once, but there is no way to retrieve atime from the provided os functions.

this is related to How can I get a file's ctime,atime,mtime and change them using Golang? , but I'd like to set less information.

This allows you to modify mtime.

package main

import (
    "fmt"
    "os"
    "syscall"
    "time"
)

func main() {
    name := "main"
    atime, mtime, ctime, err := statTimes(name)
    if err != nil {
        fmt.Println(err)
        return
    }
    fmt.Println(atime, mtime, ctime)

    // new mtime
    newMtime := time.Date(2000, time.February, 1, 3, 4, 5, 0, time.UTC)

    // set new mtime
    err = os.Chtimes(name, atime, newMtime)
    if err != nil {
        fmt.Println(err)
        return
    }

    atime, mtime, ctime, err = statTimes(name)
    if err != nil {
        fmt.Println(err)
        return
    }

    fmt.Println(atime, mtime, ctime)
}

func statTimes(name string) (atime, mtime, ctime time.Time, err error) {
    fi, err := os.Stat(name)
    if err != nil {
        return
    }
    mtime = fi.ModTime()
    stat := fi.Sys().(*syscall.Stat_t)
    atime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
    ctime = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))
    return
}

and get atime, ctime from fi.Sys().(*syscall.Stat_t)

stat := fi.Sys().(*syscall.Stat_t)
atime = time.Unix(int64(stat.Atim.Sec), int64(stat.Atim.Nsec))
ctime = time.Unix(int64(stat.Ctim.Sec), int64(stat.Ctim.Nsec))

I know that the file systems of various operating systems are different. Commonly used parts are defined in os.Fileinfo as below. https://golang.org/search?q=os.FileInfo

// A FileInfo describes a file and is returned by Stat and Lstat.
type FileInfo interface {
    Name() string       // base name of the file
    Size() int64        // length in bytes for regular files; system-dependent for others
    Mode() FileMode     // file mode bits
    ModTime() time.Time // modification time
    IsDir() bool        // abbreviation for Mode().IsDir()
    Sys() interface{}   // underlying data source (can return nil)
}

A fileStat is the implementation of FileInfo. The fileStat is declared differently for each os. https://golang.org/search?q=fileStat

linux, unix actually uses the following struct.

// A fileStat is the implementation of FileInfo returned by Stat and Lstat.
type fileStat struct {
    name    string
    size    int64
    mode    FileMode
    modTime time.Time
    sys     syscall.Stat_t
}

and Obtain ctime and atime from syscall.Stat_t.