Writing logs in Golang

Logging is essential for any application. We all know that. There is no need to explain how important it is. A module for logging comes with built-in almost all modern languages. Golang also has a built-in log module and can be used right out of the box.

fmt vs log

In the log module, there are 3 types of log messages:
1. Print — write log messages
2. Panic — write log messages and run panic() function
3. Fatal — write log messages and exit the code

These messages have the same functions as Print, Panic, and Fatal functions in fmt with a few changes.

package main

import (
 "fmt"
 "log"
)

func main() {

 fmt.Print("First print statement")
 fmt.Printf("Second print statement")
 fmt.Println("Third print statement")

 log.Print("First Log message")
 log.Printf("Second Log message")
 log.Println("Third Log message")

 l := log.Default()
 l.Print("First Log message")
 l.Printf("Second Log message")
 l.Println("Third Log message")

}

// Output
// First print statementSecond print statementThird print statement
// 2022/12/26 20:21:36 First Log message
// 2022/12/26 20:21:36 Second Log message
// 2022/12/26 20:21:36 Third Log message
// 2022/12/26 20:21:36 First Log message
// 2022/12/26 20:21:36 Second Log message
// 2022/12/26 20:21:36 Third Log message

log module has same print/panic/fatal functions as fmt module. However, there are a few differences. log module always adds a newline character at the end if it doesn’t exist. This is why all three Print statements using fmt ended in the same line but log messages were all in the same line.

This makes Print and Println functions equivalent in log module. Their implementations also are exactly the same.

Another obvious difference is that it prepends some log-related information. By default, it adds the date and time.

Customize log format

package main

import (
 "log"
 "os"
)

func main() {
 InfoLog := log.New(os.Stdout, "Info: ", log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile)
 InfoLog.Print("First Log message")

 DebugLog := log.New(os.Stdout, "Debug: ", log.Ldate|log.Ltime|log.Llongfile)
 DebugLog.Print("First Log message")

 ErrorLog := log.Default()
 ErrorLog.SetPrefix("Error: ")
 ErrorLog.SetFlags(log.Ldate | log.Ltime | log.Lmicroseconds | log.Lshortfile)
 f, err := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
 if err != nil {
  panic(err)
 }
 defer f.Close()
 ErrorLog.SetOutput(f)
 ErrorLog.Print("First Log message")
}

Output to error.log file

Error*: 2022/12/26 21:50:22.715153 main.go:23: First Log message*

Output to terminal(STDOUT)

Info: 2022/12/26 21:50:22.715100 main.go:10: First Log message
Debug: 2022/12/26 21:50:22 /home/golang/logger/main.go:13: First Log message

In the first log object, we have used New to create a new log object and assigned it to the variable InfoLog. New function requires 3 arguments:
1. os.Stdout — This defines that the log will be written to the terminal
2. “Info:” — This is the string value that prepends to log statement
3. log.Ldate|log.Ltime|log.Lmicroseconds|log.Lshortfile — This defines everything between “Info:” and the message. It generates the value 2022/12/25 21:50:22.715100 main.go:10.

Similarly, DebugLog is initialized with New and contains similar arguments.

All the arguments passed in New can be set separately using functions SetOutput, SetPrefix and SetFlags. ErrorLog uses these functions to set custom values. ErrorLog sets “error.log” as the log file.

 f, err := os.OpenFile("error.log", os.O_APPEND|os.O_CREATE|os.O_RDWR, 0666)
 if err != nil {
  panic(err)
 }
 ErrorLog.SetOutput(f)

SetOutput function requires an object of type io.Writer. This means that we can use an object of any type that has implemented Write functions. os.OpenFile returns *os.File object which conforms to io.Writer interface.

Conclusion

Setting up logs is a fundamental and integral part of programming. We have seen in the above examples that it can be done quickly using built-in log modules.

0
Subscribe to my newsletter

Read articles from NonStop io Technologies directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

NonStop io Technologies
NonStop io Technologies

Product Development as an Expertise Since 2015 Founded in August 2015, we are a USA-based Bespoke Engineering Studio providing Product Development as an Expertise. With 80+ satisfied clients worldwide, we serve startups and enterprises across San Francisco, Seattle, New York, London, Pune, Bangalore, Tokyo and other prominent technology hubs.