事情是这样的,在一个项目中,我需要读取系统中的某个文件的创建时间,根据时间做不同的处理,如超过一定时间后就删除掉。查询了一下,获取文件创建时间可以使用标准库中的os 和 syscall 来完成,但是syscall该库在不同的系统中的接口是不一样的,如在Mac下是这样使用的

package main

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

func main() {
 f, _ := os.Stat("1.txt")
 fattr, _ := f.Sys().(*syscall.Stat_t)
 fmt.Println(fattr.Ctimespec.Sec)
}

func (fs.FileInfo).Sys() interface{}*syscall.Stat_t*syscall.Win32FileAttributeData
package main

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

func main() {
 f, _ := os.Stat("1.txt")
 fattr, _ := f.Sys().(*syscall.Stat_t)
 fmt.Println(fattr.Ctime.Sec )
}


在windows中又是下面的这样

package main

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

func main() {
 f, _ := os.Stat("1.txt")
 fattr, _ := f.Sys().(*syscall.Win32FileAttributeData)
 fmt.Println(fattr.CreationTime.Nanoseconds()/1e9)
}


如果要画一个图表示大概是下面这个样子

上面的其实还不是麻烦的,如果你是在Mac上开发的,将来你的程序如果要在windows上运行的话,那么开发的时候写上适合windows的代码,就会在ide上直接报错了,也无法直接编译。

GOOS=windows  GOARCH=amd64 go build main.go
GOOS=linux  GOARCH=amd64 go build main.go
//go:build 
//go:build darwin

package main

import (
 "errors"
 "os"
 "syscall"
)

func GetCtime(path string) (int64, error) {
 finfo, err := os.Stat(path)
 if err != nil {
  return 0, err
 }
 fattr, ok := finfo.Sys().(*syscall.Stat_t)
 if !ok {
  return 0, errors.New("获取文件属性失败")
 }
 return fattr.Ctimespec.Sec, nil
}


//go:build darwin
//go:build linux

package main

//go:build windows

package main

go:build 的逻辑关系

go:build 标签可以有逻辑关系的,有且(AND),或(OR)非(NOT),比如我想要设置某个文件在darwin或liunx系统时编译,可以使用

//go:build darwin || linux 

也可以是且(AND)和或(OR)的关系混合

//go:build (darwin && amd64) || linux

自定义标签

除了GOOS和GOARCH,我们也可以自定义一些标签,如dev,release

//go:build dev

go build -tags "dev" .