doumu5662
doumu5662
2017-06-21 05:46

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

已采纳

I created a Global Logger in a utils package's init() method.

```

 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
}

```

So, I can use it like this:

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

My question is: Should I close the log file? How?

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 复制链接分享
  • 邀请回答

1条回答

  • dty97501 dty97501 4年前

    By default, os.File will be finalized by the Garbage Collector (GC) when application exit. From SetFinalizer documentation

    The finalizer for obj is scheduled to run at some arbitrary time after obj becomes unreachable. There is no guarantee that finalizers will run before a program exits, so typically they are useful only for releasing non-memory resources associated with an object during a long-running program. For example, an os.File object could use a finalizer to close the associated operating system file descriptor when a program discards an os.File without calling Close, but it would be a mistake to depend on a finalizer to flush an in-memory I/O buffer such as a bufio.Writer, because the buffer would not be flushed at program exit.

    If you don't want to rely on GC, you can close it manually in the main function as follows:

    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
        //...
    }
    

    In the above code, we use defer statement to ensure the handler will be closed when the application exit. Since Logger.Out may be defined as io.Writer, we need to test whether the Logger.Out also implements io.Closer, and if yes, it will be closed. If Logger.Out is an os.File, we also call Sync() to ensure all the content is written to disk.

    EDIT
    Quote documentation and add file.Sync() to ensure file content is written to disk.

    点赞 评论 复制链接分享