This is the 28th day of my participation in Gwen Challenge
How to play the GO log
Last time we shared the timer of GO and the timed task cron, let’s review:
- What is the Timer
- How to use Timer
- What is the Ticker
- How is Ticker used
- What is the cron
- How to use Cron
For answers to these questions, check out GO’s Timer and timed task Cron
Today let’s take a look at the GO standard library log package
Specific source path: SRC /log/log.go
How to use the log package easily
Let’s see what happens when we use the log package in the editor
At first glance, the log package involves these methods and data structures, not complicated at all, as shown in the figure above
Let’s take a look at the data structure
package main
import "log"
func main(a) {
log.Println("The little devil boy hits the log... ")
test := "Hello wrold "
// Printf has a format control
log.Printf("%s little devil boy hit log... \n", test)
log.Fatalln("The boy hit the log, triggering the Fatal.")
log.Panicln("The little devil kid hit the log and set off Panic.")}Copy the code
Running the code above gives the following effect:
20201/06 /xx XX :25:53 Little devil boy play log... 20201/06 /xx xx:25:53 Hello word... 2011/06 /xx XX :25:53 Fatal exit status 1Copy the code
By default, the date, time, and printed content can be printed
How do you configure log and how does it work
Using the log package in GO, we use the default log that is definitely not enough, for example, the log printed in the above small case, you do not know which line of code is printed out, and set the log to be printed in the log file, etc
Let’s take a look at how to configure the log, starting with creating logger. Okay
Create a newlogger
Let’s add a prefix to the basic log
func main(a) {
// Print to standard output
myLog := log.New(os.Stdout, "<XMT>", log.Lshortfile|log.Ldate|log.Ltime)
myLog.Println("The bewitched boy printed a log with a prefix... ")}Copy the code
The execution effect is as follows:
<XMT>2021/06/28 12:35:47 main.go:20: The imp printed a log with a prefix...Copy the code
Let’s look at an implementation of the log.new method
Specific source path: SRC /log/log.go
func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out: out, prefix: prefix, flag: flag}
}
Copy the code
The func New(out IO.Writer, prefix string, flag int) *Logger method calls the Logger data structure
// A Logger represents an active logging object that generates lines of
// output to an io.Writer. 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 sync.Mutex // ensures atomic writes; protects the following fields
prefix string // prefix on each line to identify the logger (but see Lmsgprefix)
flag int // properties
out io.Writer // destination for output
buf []byte // for accumulating text to write
}
Copy the code
The type Logger struct has these members, and it looks like each parameter is easy to understand
- mu sync.Mutex
Lock to ensure atomic operation
- prefix string
The prefix of each log line
- out io.Writer
Output location, either file or standard output
- buf []byte
Buffer of buffers
- flag int
Specific attributes, we can see through the source code, specific attributes have the following options
These parameters are used to control the details of the log output, such as time, number of lines of code, prefix, and so on
const (
Ldate = 1 << iota // the date in the local time zone: 2009/01/23
Ltime // the time in the local time zone: 01:23:23
Lmicroseconds // Microsecond Resolution: 01:23:23.123123. Assumes Ltime.
Llongfile // full file name and line number: /a/b/c/d.go:23
Lshortfile // final file name element and line number: d.go:23. overrides Llongfile
LUTC // if Ldate or Ltime is set, use UTC rather than the local time zone
Lmsgprefix // move the "prefix" from the beginning of the line to before the message
LstdFlags = Ldate | Ltime // initial values for the standard logger
)
Copy the code
Source code to write notes or very clear, specific each field is to do what, after using what kind of effect, according to the notes, at a glance
Let’s check the source code to know, why the above small case, log inside the default output date, time, specific content, because the log package will default New a log, for our default use
Var STD = New(os.stderr, “”, LstdFlags) New
LstdFlags = Ldate | Ltime // initial values for the standard logger
LstdFlags property, which prints the date and time by default
// Println calls l.Output to print to the logger.
// Arguments are handled in the manner of fmt.Println.
func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
Copy the code
(l *Logger) Println does the actual Output, calling (L *Logger) Output
// Output writes the output for a logging event. The string s contains
// the text to print after the prefix specified by the flags of the
// Logger. A newline is appended if the last character of s is not
// already a newline. Calldepth is used to recover the PC and is
// provided for generality, although at the moment on all pre-defined
// paths it will be 2.
func (l *Logger) Output(calldepth int, s string) error {
now := time.Now() // get this early.
var file string
var line int
l.mu.Lock()
defer l.mu.Unlock()
ifl.flag&(Lshortfile|Llongfile) ! =0 {
// Release lock while getting caller info - it's expensive.
l.mu.Unlock()
var ok bool
_, file, line, ok = runtime.Caller(calldepth)
if! ok { file ="?????"
line = 0
}
l.mu.Lock()
}
l.buf = l.buf[:0]
l.formatHeader(&l.buf, now, file, line)
l.buf = append(l.buf, s...)
if len(s) == 0 || s[len(s)- 1] != '\n' {
l.buf = append(l.buf, '\n')
}
_, err := l.out.Write(l.buf)
return err
}
Copy the code
Func (l *Logger) Output(calldepth int, s string) error {the function does the following:
- Concatenate log string data
- Output to the
out
In, hereout
The default is standard output, or you can set the output to a file yourself
Configure a Logger
Let’s use log to set the output log to the file
func main(a) {
logFile, err := os.OpenFile("./XMT.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
iferr ! =nil {
fmt.Println("os.OpenFile error :", err)
return
}
// Set the output position, there is a lock to control
log.SetOutput(logFile)
// Set log properties
log.SetFlags(log.Llongfile | log.Ltime | log.Ldate)
// Prints logs
log.Println("The little devil boy's new journal... ")
// Manually set the prefix
log.SetPrefix(【 Key points 】)
log.Println("The little devil boy's important journal...")}Copy the code
Running the code above gives the following effect:
2021/06/28 12:57:14 D:/mycode/my_new_first/my_log/main.go:36: New diary of the little devil Boy... [key]2021/06/28 12:57:14 D:/mycode/my_new_first/my_log/main.go:40: Important journal of the little devil Boy...Copy the code
-
log.SetOutput
SetOutput(w IO.Writer) is a call to func (L *Logger) SetOutput(w IO.Writer)
func (l *Logger) SetOutput(w io.Writer) {
l.mu.Lock()
defer l.mu.Unlock()
l.out = w
}
Copy the code
- log.SetFlags
Log.SetFlags actually calls the corresponding SetFlags method for Logger
The same goes for SetPrefix
// SetFlags sets the output flags for the logger.
// The flag bits are Ldate, Ltime, and so on.
func (l *Logger) SetFlags(flag int) {
l.mu.Lock()
defer l.mu.Unlock()
l.flag = flag
}
Copy the code
conclusion
- How to use
log
包 log
Package principle and implementation- Custom Logs
Welcome to like, follow and favorites
Writing is not easy, my friends
Your support and encouragement is my motivation to persist in sharing and improve quality
Well, that’s it for now, unit testing and performance testing for GO
Technology is open, our mentality, should be more open. Embrace change, live in the sun, and strive to move forward.
I am Nezha, welcome to like, see you next time ~