美文网首页
聊聊golang的log

聊聊golang的log

作者: go4it | 来源:发表于2020-12-03 23:59 被阅读0次

    本文主要研究一下golang的log

    log

    flags

    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
    )
    

    这几个flags可以用来设置log的pattern

    logger

    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
    }
    
    func New(out io.Writer, prefix string, flag int) *Logger {
        return &Logger{out: out, prefix: prefix, flag: flag}
    }
    
    func (l *Logger) SetOutput(w io.Writer) {
        l.mu.Lock()
        defer l.mu.Unlock()
        l.out = w
    }
    
    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()
        if l.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
    }
    
    func (l *Logger) Printf(format string, v ...interface{}) {
        l.Output(2, fmt.Sprintf(format, v...))
    }
    
    func (l *Logger) Print(v ...interface{}) { l.Output(2, fmt.Sprint(v...)) }
    
    func (l *Logger) Println(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) }
    
    func (l *Logger) Fatal(v ...interface{}) {
        l.Output(2, fmt.Sprint(v...))
        os.Exit(1)
    }
    
    func (l *Logger) Fatalf(format string, v ...interface{}) {
        l.Output(2, fmt.Sprintf(format, v...))
        os.Exit(1)
    }
    
    func (l *Logger) Fatalln(v ...interface{}) {
        l.Output(2, fmt.Sprintln(v...))
        os.Exit(1)
    }
    
    func (l *Logger) Panic(v ...interface{}) {
        s := fmt.Sprint(v...)
        l.Output(2, s)
        panic(s)
    }
    
    func (l *Logger) Panicf(format string, v ...interface{}) {
        s := fmt.Sprintf(format, v...)
        l.Output(2, s)
        panic(s)
    }
    
    func (l *Logger) Panicln(v ...interface{}) {
        s := fmt.Sprintln(v...)
        l.Output(2, s)
        panic(s)
    }
    
    func (l *Logger) SetFlags(flag int) {
        l.mu.Lock()
        defer l.mu.Unlock()
        l.flag = flag
    }
    
    func (l *Logger) SetPrefix(prefix string) {
        l.mu.Lock()
        defer l.mu.Unlock()
        l.prefix = prefix
    }
    
    func (l *Logger) Writer() io.Writer {
        l.mu.Lock()
        defer l.mu.Unlock()
        return l.out
    }
    
    • log包默认提供的Print、Fatal、Panic方法使用的是std标准输出流,它也提供了New方法可以自定义输出
    • Fatal相关方法会执行os.Exit(1),Panic相关方法会执行panic,而panic执行的是os.Exit(1)
    • f结尾的方法执行的是fmt.Sprintf,可以使用format,ln结尾的方法执行的是fmt.Sprintln,会增加换行

    实例

    package main
    
    import (
        "encoding/json"
        "errors"
        "io"
        "log"
        "os"
        "time"
    )
    
    var logFile *os.File
    
    func init() {
        log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
        log.SetPrefix("demo-app ")
        var err error
        logFile, err = os.OpenFile("/tmp/demo.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
        if err != nil {
            log.Fatalln("Failed to open log file")
        }
        mw := io.MultiWriter(os.Stdout, logFile)
        log.SetOutput(mw)
    }
    
    type Cart struct {
        UserId int `json:"userId"`
        SkuId  int `json:"skuId"`
    }
    
    func closeLogFile() {
        if logFile != nil {
            log.Println("closing log file")
            logFile.Close()
        }
    }
    
    func main() {
        defer closeLogFile()
        // log.Panicln("print and then exit with status 2")
        // log.Fatalln("print and then exit with status 1")
        log.Println("hello")
        log.Printf("hello %s", "abc")
    
        //print with var
        str1 := "abc"
        str2 := "cdf"
        log.Println("print with auto space:", str1, "append", str2)
    
        //print error
        err1 := errors.New("demo error")
        log.Println("error:", err1)
    
        //print time
        now1 := time.Now()
        log.Println("print time:", now1)
        log.Println("print time with format:", now1.Format(time.RFC3339))
    
        //print struct
        cart := Cart{
            UserId: 1,
            SkuId:  123,
        }
        log.Println("print struct:", cart)
    
        //print json
        jsonByte, err := json.Marshal(cart)
        if err != nil {
            log.Fatalln("error:", err)
        }
        log.Println("print cart json:", string(jsonByte))
    
        //log to file
    }
    
    • 这里给log设置了MultiWriter,可以同时往std和文件输出

    输出实例

    demo-app 2020/12/03 23:54:27.245848 main.go:42: hello
    demo-app 2020/12/03 23:54:27.245974 main.go:43: hello abc
    demo-app 2020/12/03 23:54:27.245981 main.go:48: print with auto space: abc append cdf
    demo-app 2020/12/03 23:54:27.245996 main.go:52: error: demo error
    demo-app 2020/12/03 23:54:27.246015 main.go:56: print time: 2020-12-03 23:54:27.246001 +0800 CST m=+0.000260928
    demo-app 2020/12/03 23:54:27.246022 main.go:57: print time with format: 2020-12-03T23:54:27+08:00
    demo-app 2020/12/03 23:54:27.246047 main.go:64: print struct: {1 123}
    demo-app 2020/12/03 23:54:27.246109 main.go:71: print cart json: {"userId":1,"skuId":123}
    demo-app 2020/12/03 23:54:27.246116 main.go:33: closing log file
    

    小结

    • log包默认提供的Print、Fatal、Panic方法使用的是std标准输出流,它也提供了New方法可以自定义输出
    • Fatal相关方法会执行os.Exit(1),Panic相关方法会执行panic,而panic执行的是os.Exit(1)
    • f结尾的方法执行的是fmt.Sprintf,可以使用format,ln结尾的方法执行的是fmt.Sprintln,会增加换行

    doc

    相关文章

      网友评论

          本文标题:聊聊golang的log

          本文链接:https://www.haomeiwen.com/subject/ipqbwktx.html