SoFunction
Updated on 2025-03-05

Introduction to log library in Go language

1. Introduction to the standard library log

  • The built-in log package in Go language implements simple logging services.

1. Use Logger

  • The log package defines the Logger type, which provides some methods to format the output.
  • The log package also provides a predefined "standard" logger that can be used by calling the functions Print series (Print|Printf|Println), Fatal series (Fatal|Fatalf|Fatalln), and Panic series (Panic|Panicf|Panicln), which is easier to use than creating a logger object by yourself.

The logger will print the date and time of each log information, and the default output to the system's standard error.

The Fatal series of functions will be called (1) after writing log information.

Panic series functions will panic after writing log information.

Example:

// Directly call print to output logs to the terminalfunc main() {
	("This is a very ordinary log.")
	v := "Very ordinary"
	("This is a %s log.\n", v)
	("This is a log that triggers fatal.")
	("This is a log that triggers panic.")
}

2. Configure logger

2.1. Configuration of standard logger

  • By default, logger will only provide log time information, but in many cases we want to get more information, such as recording the file name and line number of the log.
  • The log standard library provides us with a way to customize these settings. The Flags function in the log standard library will return the output configuration of the standard logger, and the SetFlags function is used to set the output configuration of the standard logger.

2. Custom log library

1. Needs to be met

1. Support log output in different places on the network

2. The log must support switch control

3. The complete log should include time, line number, file name, log level, and log information.

4. Log files must be able to be cut

5. Log level

  • Debug
  • Trace
  • Info
  • Warning
  • Error
  • Fatal

2. Learn about the runtime package

  • The () method will return the information of the function call, and pass int type data into () to represent the number of layers called (0 means the first layer is called, 1 means the second layer, and so on). () returns the following four parameters:

pc: Records the called function message, such as function name, etc.
file: The name of the call
line: number of lines
OK: The returned bool value

// Get the line number of codefunc getinfo(n int) {
	/*
		 () Returns four parameters:
		 pc: Records the called function message, such as function name, etc.
		 file: The name of the call
		 line: number of lines
		 OK: The returned bool value
	 */
	pc, file, line, ok := (n)
	if !ok {
		("() failed\n")
		return
	}
	(pc)  // Used to call function messages	funcName := (pc).Name() // Use the () method and parameter pc serial number to call out the function name	(funcName)
	(file)   // Print out the absolute path to the executed file	((file))  // The () method can get the last file name of the absolute path passed in	(line)   // Print out the executed line number}

func main() {
	getinfo(0)
}

3. Custom log library

1. Create a new mylogger package directory under the E:\GoProject\src\ project directory and store the log library code

In the file in the mylogger package directory, put the code that outputs the log to the terminal

# E:\GoProject\src\\mylogger\

package mylogger

import (
	"fmt"
	"strings"
	"time"
)

// The log content output by the terminal
// Logger log structuretype ConsoleLogger struct {
	Level LogLevel
}

// Constructorfunc NewLog(levelStr string) ConsoleLogger {
	level, err := parseLogLevel(levelStr)
	if err != nil {
		panic(err)
	}
	return ConsoleLogger{
		Level: level,
	}
}

// Define log level comparisonfunc (c ConsoleLogger) enable(level LogLevel) bool {
	return  <= level
}

// Define a log printing methodfunc (c ConsoleLogger) outLog(lv LogLevel, format string, a ...interface{}) {
	level := parseLogLevelStr(lv)
	if (lv) {
		msg := (format, a...) // Support formatting operations, a... means expanding the received interface		level = (level)
		fileName, funcName, linenu := getinfo(3)
		("[%s] [%s] [FileName:%s lineNum:%d:%s] %s\n", ().Format("2006-01-02 15:04:05"), level, fileName, linenu, funcName, msg)
	}
}

// Debug logfunc (c ConsoleLogger) Debug(msg string, a ...interface{}) {
	(DEBUG, msg, a...)
}

// Info logfunc (c ConsoleLogger) Info(msg string, a ...interface{}) {
	(INFO, msg, a...)
}

// Warning logfunc (c ConsoleLogger) Warning(msg string, a ...interface{}) {
	(WARNING, msg, a...)
}

// Error logfunc (c ConsoleLogger) Error(msg string, a ...interface{}) {
	(ERROR, msg, a...)
}

// Fatal logfunc (c ConsoleLogger) Fatal(msg string, a ...interface{}) {
	(FATAL, msg, a...)
}

In the file in the mylogger package directory, put the code that outputs the log to the file

# E:\GoProject\src\\mylogger\

package mylogger

//Related operations for writing logs to files
import (
	"fmt"
	"os"
	"path"
	"strings"
	"time"
)

// Logger log structuretype FileLogger struct {
	Level       LogLevel
	logPath     string // Log file directory	fileName    string // Log file name	maxFileSize int64  // Log file size	fileObj     *
	errFileObj  *
}

// Constructorfunc NewFileLog(levelStr, fp, fn string, maxSize int64) *FileLogger {
	level, err := parseLogLevel(levelStr)
	if err != nil {
		panic(err)
	}
	f1 := &FileLogger{
		Level:       level,
		logPath:     fp,
		fileName:    fn,
		maxFileSize: maxSize,
	}
	err = ()
	if err != nil {
		panic(err)
	}
	return f1
}

// Define the file initialization method and open the filefunc (f *FileLogger) initFile() error {
	// Open the file	fullPath := (, )
	fileObj, err := (fullPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		("open logFile failed,Err:%v", err)
		return err
	}
	// Open the error log file	errFileObj, err := ("error-"+fullPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		("open errorLogFile failed,Err:%v", err)
		return err
	}
	// Assign the file handle to the element in the structure	 = fileObj
	 = errFileObj
	return nil
}

// Close file methodfunc (f *FileLogger) closeFile() {
	()
	()
}

// Define log level comparisonfunc (f *FileLogger) enable(level LogLevel) bool {
	return  <= level
}

// Define the method to check the log size for cuttingfunc (f *FileLogger) checkLogSize(file *) bool { // The file handle types opened using the () method are * This pointer type	fileInfo, err := ()
	if err != nil {
		("get file info failed,err:%v\n", err)
		return false
		// panic(err)
	}
	if () >  {
		return true
	}
	return false
}

func (f *FileLogger) cutFile(file *) (*, error) {
	// Get the current file name	fileInfo, err := ()
	if err != nil {
		("get file info failed,err:%v\n", err)
		return nil, err
	}
	append := "_" + ().Format("2006-01-02-15-04-05") + ".log" // Timestamp suffix	fileName := ()
	newFileName := fileName + append
	oldPath := (, fileName) // Full path to log file	newPath := (, newFileName)
	// Close the current file handle	()
	// Make a name change backup	(oldPath, newPath)
	// Open another file	fileObj, err := (oldPath, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
	if err != nil {
		("open logFile failed,Err:%v\n", err)
		return nil, err
	}
	return fileObj, nil
}

// Define a log output methodfunc (f *FileLogger) outLog(lv LogLevel, format string, a ...interface{}) {
	level := parseLogLevelStr(lv)
	if (lv) {
		msg := (format, a...) // Support formatting operations, a... means expanding the received interface		level = (level)
		fileName, funcName, linenu := getinfo(3)
		// Determine whether the log needs to be cut		if () {
			fileobj, err := ()
			if err != nil {
				("log cut failed,err:%v\n", err)
			}
			 = fileobj
		}
		// Record the log in the log file		(, "[%s] [%s] [FileName:%s lineNum:%d:%s] %s\n", ().Format("2006-01-02 15:04:05"), level, fileName, linenu, funcName, msg)
		if lv >= ERROR {
			// Determine whether the error log needs to be cut			if () {
				fileobj, err := ()
				if err != nil {
					("log cut failed,err:%v\n", err)
				}
				 = fileobj
			}
			//Recorate the log level greater than ERROR again in the error log			(, "[%s] [%s] [FileName:%s lineNum:%d:%s] %s\n", ().Format("2006-01-02 15:04:05"), level, fileName, linenu, funcName, msg)
		}
	}
}

// Debug logfunc (f *FileLogger) Debug(msg string, a ...interface{}) {
	(DEBUG, msg, a...)
}

// Info logfunc (f *FileLogger) Info(msg string, a ...interface{}) {
	(INFO, msg, a...)
}

// Warning logfunc (f *FileLogger) Warning(msg string, a ...interface{}) {
	(WARNING, msg, a...)
}

// Error logfunc (f *FileLogger) Error(msg string, a ...interface{}) {
	(ERROR, msg, a...)
}

// Fatal logfunc (f *FileLogger) Fatal(msg string, a ...interface{}) {
	(FATAL, msg, a...)
}

Create files in the mylogger package directory and place the shared code in the package

# E:\GoProject\src\\mylogger\

package mylogger

import (
	"errors"
	"fmt"
	"path"
	"runtime"
	"strings"
)

// Set log leveltype LogLevel uint16

const (
	UNKNOWN LogLevel = iota
	DEBUG
	TRACE
	INFO
	WARNING
	ERROR
	FATAL
)

// parse the log level and parse the string into intfunc parseLogLevel(s string) (LogLevel, error) {
	s = (s) // Convert all strings to lowercase	switch s {
	case "debug":
		return DEBUG, nil
	case "trace":
		return TRACE, nil
	case "info":
		return INFO, nil
	case "warning":
		return WARNING, nil
	case "error":
		return ERROR, nil
	case "fatal":
		return FATAL, nil
	default:
		err := ("Invalid log level")
		return UNKNOWN, err
	}
}

// Parses log levels into stringsfunc parseLogLevelStr(lv LogLevel) (s string) {
	s = (s) // Convert all strings to lowercase	switch lv {
	case DEBUG:
		return "DEBUG"
	case TRACE:
		return "TRACE"
	case INFO:
		return "INFO"
	case WARNING:
		return "WARNING"
	case ERROR:
		return "ERROR"
	case FATAL:
		return "FATAL"
	default:
		return "DEBUG"
	}
}

// Get the line number of codefunc getinfo(n int) (fileName, funcName string, line int) {
	/*
		 () Returns four parameters:
		 pc: Records the called function message, such as function name, etc.
		 file: The name of the call
		 line: number of lines
		 OK: The returned bool value
	 */
	pc, file, line, ok := (n)
	if !ok {
		("() failed\n")
		return
	}
	fileName = (file)
	funcName = (pc).Name()
	return fileName, funcName, line
}

2. Call log library code test

It should be noted that importing mylogger package starts from the $GOPATH path (that is, the relative path starting from the src directory)

# E:\GoProject\src\\LTP\logging

package main

import (
	"time"

	mylogger "/mylogger"
)


func main() {
	id := 10
	name := "Xiao Ming"
	flogger := ("info", "./", "", 1024)
	for {
		("This is a Warning log")
		("This is an Error log, id:%d name:%s", id, name)
		(2 * )
	}
}

This is all about this article about Go log library. For more information about Go log library, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!