3
\$\begingroup\$

My code works in that it compiles, and when executed writes out a log file using a buffered writer.

But I wonder whether:

  1. I am correct in assuming that this actually winds up deferring a .Close that is always called
  2. a package variable is the idiomatic way of doing this in Go

I realise that I could just have createLogger return the file pointer, and defer on that ... but that seems even weirder, to have createLogger set a package variable on log, then return the file pointer to be treated as a local ...

I'm still struggling with an idiom here.

package main

import (
    "bufio"
    "log"
    "os"
)

var logFile *os.File

func main() {
    createLogger()
    defer logFile.Close()

    // do some stuff
}

func createLogger() {
    logFile, err := os.OpenFile("log/app.log", os.O_RDWR|os.O_CREATE|os.O_APPEND, 0666)
    if err != nil {
        log.Fatalf("error opening file: %v", err)
        os.Exit(-1)
    }
    log.SetOutput(bufio.NewWriter(logFile))
}
\$\endgroup\$
3
\$\begingroup\$

Yes, on both counts (although putting it in the main package is not).

Typically I would return a logFile from createLogger (calling it newLogger is idiomatic), and defer closing the result.

If you're building a logger to work across your whole app, I'd look at how the standard library does it.

Essentially, create a new package my_app_logger with an initializer which sets up the logger. That way, every package that includes my_app_logger gets the same logger instance.

\$\endgroup\$
  • \$\begingroup\$ Thanks - yes, that all makes sense. I'm actually teaching myself Go as I ... go ... by writing a CLI app. Everything started out in main() and then as I add functionality I'm refactoring. \$\endgroup\$ – Duncan Bayne Aug 12 '14 at 3:46

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.