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 theoutIn, hereoutThe 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 uselog
  • logPackage 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 ~