introduction:
Logging is important in our daily programming. As long as we write the code, there may be bugs. Log files are a way to quickly find these bugs and better understand the working status of the program.
Let's take a look at the definition of the log file:
Log filesIs a file that records events or messages between different users of the communication software that occur during the operation of the operating system or other software. Recording is the act of saving logs.
Logs are the eyes and ears of developers that can be used to track, locate errors, debug and analyze code, and monitor application performance. In the simplest case, messages are written to a single log file.
Go language standard library log package
Because logging is important, the Go language standard library provideslog
package, we can make some simple configurations for logs, and we can customize a set of our own loggers.
In Golanglog
package implements a simple logging package. It defines a type, a Logger, and a method for formatting the output. It also has a predefined "standard" logger that can be accessed through helper functionsPrint[f|ln]
、Fatal[f|ln]
andPanic[f|ln]
Access, they are easier to use than creating a logger manually.
Basic log entries include: prefix, date and timestamp, which source file is recorded by the log, the line where the source file records the log, and finally the log message. Let's take a look at the simple uselog
Package: The message when the 0 is divided during division operation returns to the program instead of directly exiting the program.
package main import ( "errors" "fmt" "log" ) func myDiv(x float64, y float64) (float64, error) { if y == 0 { return 0, ("The dividend cannot be 0") } return x / y, nil } func main() { var x float64 = 128.2 var y float64 res, err := myDiv(x, y) if err != nil { (err) // Print Write to standard logger} (res) }
Run the program:
$ go run
2022/04/19 23:18:06 Divisor cannot be 0
0
In the above program, we imported three packages:errors
、fmt
、log
。
Then usedlog
In the packagePrint
Function: At this time the logger will write standard errors and print the date and time of each logged message, which is very useful in general. Each log message has an output on a separate line: if the message being printed does not end on a new line, the logger will add a line.
In addition,log
In the packageFatal
The function is called after writing a log message (1)
。
func main() { var x float64 = 128.2 var y float64 res, err := myDiv(x, y) if err != nil { (err) // After calling Print(), it will be called (1)} (res) } // 2022/04/19 23:22:44 The dividend cannot be 0// exit status 1
AndPanic
The function is called after writing a log message panic
, unless the program executesrecover()
function, otherwise it will cause the program to terminate after printing the call stack.
func main() { var x float64 = 128.2 var y float64 res, err := myDiv(x, y) if err != nil { (err) // Panic will call Print() and then use panic()} (res) }
Running results:
2022/04/19 23:24:18 The dividend cannot be 0
panic: The dividend cannot be 0
goroutine 1 [running]:
({0xc000086f60?, 0xc000086f70?, 0x404f99?})
/usr/local/go/src/log/:385 +0x65
()
/home/wade/go/src/logLearning/:26 +0x65
exit status 2
From this we can see thatPrint
Series functions are the standard method for writing log messages.
How to store log messages in a file in Go
In the above code, simply printing the log message to the console is far from enough, because the console is real-time, and if the console log message is closed, it will be closed.
Given that we have learned how Go language can read files, we can store log messages in a file and store all logs in that file.
package main import ( "errors" "fmt" "log" "os" ) func myDiv(x float64, y float64) (float64, error) { if y == 0 { return 0, ("The dividend cannot be 0") } return x / y, nil } func main() { var x float64 = 128.2 var y float64 res, exception := myDiv(x, y) file, err := ("", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) if err != nil { (err) } defer () // Close the file(file) (exception) (res) }
Run the code:
$ go run
0
In addition, we will find that there is an additional created in the directory
File. Open the file and you will see something like the one below printed out.
Customize your logger
To create a custom logger, we need to create aLogger
Type structure, and then configure each logger with an output destination, prefix, and flag. And each logger is multiple goroutines safe, eachLogger
Structures have a mutex, meaning that multiple goroutines can call these functions from the same logger at the same time without writing conflicts with each other. Let's take a look Logger
The underlying implementation of the structure:
Logger structure
// A Logger represents an active logging object that generates lines of // output to an . Each logging operation makes a single call to // the Writer's Write method. A Logger can be used simultaneously from // multiple goroutines; it guarantees to serialize access to the Writer. type Logger struct { mu // ensures atomic writes; protects the following fields prefix string // prefix on each line to identify the logger (but see Lmsgprefix) flag int // properties out // destination for output buf []byte // for accumulating text to write }
Then let's look at a sample program:
package main import ( "io" "io/ioutil" "log" "os" ) var ( Trace * // Record all logsInfo * // Important informationWarning * // Warning messageError * // error message) func init() { file, err := ("", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { ("Failed to open error log file: ", err) } Trace = (, "Trace: ", ||) Info = (, "Info: ", ||) Warning = (, "Warning: ", ||) Error = ((file, ), "Error: ", ||) } func main() { ("hello") ("Information") ("Warning") ("Error") }
Running results:
Info: 2022/04/20 00:37:34 :36: Information
Warning: 2022/04/20 00:37:34 :37: Warning
Error: 2022/04/20 00:37:34 :38: Error
Uselog
PackedNew
Function, create and initialize a value of type Logger, and thenNew
The function returns the address of the newly created value.
New function
func New(out , prefix string, flag int) *Logger { return &Logger{out: out, prefix: prefix, flag: flag }
- The first parameter of the New function
out
Specifies the destination to be written to the log, and the value passed in this parameter must be implemented.Interface
- The second parameter
prefix
It will appear at the beginning of each row of logs generated - The third parameter
flag
Define what attributes are included in the log
In this program:
- Trace logger is used
ioutil
The Discard variable in the package is used as the destination to write. All Writer calls will not have any action, but will return successfully. When a level of log is not important, the Discard variable can be used to disable the level of logs. - Loggers Info and Warning both use stdout as log output.
- Logging the first parameter of the New function in Error is used.
MultiWriter
Function, this function call will return aThe value of the interface type, which contains the file file that was opened before and stderr. This function is a variable parameter function that can accept any implementation.
The value of the interface will be passed in
Binding together. When writing this return value, it will be bound to all the
Values are written. This enables output to multiple Writers. The advantage of this is that when logging using the Error logger,The output will be written to the file and stderr at the same time。
Summarize
Golanglog
The implementation of the package is based on long-term practice and accumulation of the need to record logs. For example, write the output tostdout
, log the log tostderr
, this is also a method used by many programs based on command line interfaces.
The first thing to do when writing a log is to find a perfect library. Then, after you have selected the log library, you also need to plan where to call the logger in your code, how to store the logs, how to make them available at any given time, and how to analyze them.
The best practice for Go logging is to call custom loggers from the main application process, not in goroutines. At the same time, log messages in the application should be written to the local file to be permanently saved. At the same time, reminders should be given for error information, which is convenient for timely location and processing.
This is the end of this article about how to use log packages in Go. For more related contents of Go using log packages, please search for my previous articles or continue browsing the related articles below. I hope everyone will support me in the future!