本文次要钻研一下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 mainimport (    "encoding/json"    "errors"    "io"    "log"    "os"    "time")var logFile *os.Filefunc 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: hellodemo-app 2020/12/03 23:54:27.245974 main.go:43: hello abcdemo-app 2020/12/03 23:54:27.245981 main.go:48: print with auto space: abc append cdfdemo-app 2020/12/03 23:54:27.245996 main.go:52: error: demo errordemo-app 2020/12/03 23:54:27.246015 main.go:56: print time: 2020-12-03 23:54:27.246001 +0800 CST m=+0.000260928demo-app 2020/12/03 23:54:27.246022 main.go:57: print time with format: 2020-12-03T23:54:27+08:00demo-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

  • log