我应该关闭Go中的日志文件吗?

时间:2017-06-21 05:46:46

标签: logging go

我在utils包的Logger方法中创建了一个全局init()

```

 package utils

 var Logger *log.Logger

 func init() {

  logFile, _ := config.Configure.String("log_file")
  if len(logFile) == 0 {
     appRoot, _ := os.Getwd()
     logFile = filepath.Join(appRoot, "app_runtime.log")
  }

  f, err := os.OpenFile(logFile, os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0666)
  //Look HERE!!! 

  if err != nil {
     panic(err)
  }
  Logger = log.New()

  //Log as JSON
  Logger.Formatter = &log.JSONFormatter{}

  //Output to stdout
  //When production, use file
  Logger.Out = f

  // Only log the debug severity or above.
  Logger.Level = log.DebugLevel
}

```

所以,我可以这样使用它:

utils.Logger.Info("This is debug info")

我的问题是:我应该关闭日志文件吗?怎么样?

1 个答案:

答案 0 :(得分:1)

默认情况下,当应用程序退出时,垃圾收集器(GC)将最终确定os.File。来自SetFinalizer文档

  

obj的终结器计划在obj无法访问后的某个任意时间运行。无法保证终结器将在程序退出之前运行,因此通常它们仅用于在长时间运行的程序期间释放与对象关联的非内存资源。例如,当程序在不调用Close的情况下丢弃os.File时,os.File对象可以使用终结器关闭关联的操作系统文件描述符,但是依赖于终结器来刷新内存中的I是错误的。 / O缓冲区,如bufio.Writer,因为缓冲区不会在程序退出时刷新。

如果您不想依赖GC,可以在main功能中手动关闭它,如下所示:

func main() {
    //Close log writer when exit
    defer func(){
        if file, ok := Logger.Out.(*os.File); ok {
            file.Sync()
            file.Close()
        } else if handler, ok := Logger.Out.(io.Closer); ok {
            handler.Close()
        }
    }()

    //Your original codes
    //...
}

在上面的代码中,我们使用defer语句来确保在应用程序退出时关闭处理程序。由于Logger.Out可能被定义为io.Writer,因此我们需要测试Logger.Out是否也实现io.Closer,如果是,则会关闭它。如果Logger.Outos.File,我们也会调用Sync()以确保所有内容都写入磁盘。

修改
引用文档并添加file.Sync()以确保将文件内容写入磁盘。