700字范文,内容丰富有趣,生活中的好帮手!
700字范文 > Go标准库日志打印 以及同时输出到控制台和文件

Go标准库日志打印 以及同时输出到控制台和文件

时间:2019-08-28 16:41:31

相关推荐

Go标准库日志打印 以及同时输出到控制台和文件

打印

在使用go写一些小程序时,我们没必要引入额外的包,直接使用fmt标准包打印即可:

import "fmt"func main() {fmt.Println("line1")fmt.Print("line2")fmt.Printf("line%d \n", 3)str1 := fmt.Sprintln("hello", 3)str2 := fmt.Sprint("hello ", 1, " 2")str3 := fmt.Sprintf("hello %d", 1)fmt.Print(str1, str2, str3)}

line1line2line3 hello 3hello 1 2hello 1

那么,有些场景下,我们希望能同时打印到日志文件中要怎么办呢?

log包

标准库提供了log组件,用法和fmt一致,有3种方式:

import “log"func main() {log.Println("line1")log.Print("line2")log.Printf("line%d \n", 3)}

和fmt的区别就是多了时间:

/08/25 17:23:47 line1/08/25 17:23:47 line2/08/25 17:23:47 line3

我们通过SetFlag函数,可以设置打印的格式:

// For example, flags Ldate | Ltime (or LstdFlags) produce,// /01/23 01:23:23 message// while flags Ldate | Ltime | Lmicroseconds | Llongfile produce,// /01/23 01:23:23.123123 /a/b/c/d.go:23: messageconst (Ldate = 1 << iota// the date in the local time zone: /01/23Ltime// the time in the local time zone: 01:23:23Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime.Llongfile // full file name and line number: /a/b/c/d.go:23Lshortfile// final file name element and line number: d.go:23. overrides LlongfileLUTC// if Ldate or Ltime is set, use UTC rather than the local time zoneLmsgprefix// move the "prefix" from the beginning of the line to before the messageLstdFlags= Ldate | Ltime // initial values for the standard logger)

比如,我们只需要时间和文件名:

import “log"func main() {log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)log.Println("line1")log.Print("line2")log.Printf("line%d \n", 3)}

此时,再次运行,则会打印文件和行号:

/08/25 17:27:56 mod_unread_redis.go:32: line1/08/25 17:27:56 mod_unread_redis.go:33: line2/08/25 17:27:56 mod_unread_redis.go:34: line3

如何输出日志到文件?

log包使用非常简单,默认情况下,只会输出到控制台。

我们可以使用SetOutput改变输出流,比如输出到文件。

先来看一下函数原型,其接收一个io.Writer接口:

// SetOutput sets the output destination for the standard logger.func SetOutput(w io.Writer) {// ...}

那么,我们就可以创建一个文件流设置一下就行了。

// 创建、追加、读写,777,所有权限f, err := os.OpenFile("log.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)if err != nil {return}defer func() {f.Close()}()log.SetOutput(f)

此时,在运行,我们发现日志会输出到文件,但是控制台没有任何东西输出了。

如何同时输出到控制台和文件?

标准库io包中,有一个MultiWriter,可以把文件流和控制台标准输出流整合到一个io.Writer上,其实现上就是一个数组,在执行写操作时,遍历数组:

// MultiWriter creates a writer that duplicates its writes to all the// provided writers, similar to the Unix tee(1) command.//// Each write is written to each listed writer, one at a time.// If a listed writer returns an error, that overall write operation// stops and returns the error; it does not continue down the list.func MultiWriter(writers ...Writer) Writer {allWriters := make([]Writer, 0, len(writers))for _, w := range writers {if mw, ok := w.(*multiWriter); ok {allWriters = append(allWriters, mw.writers...)} else {allWriters = append(allWriters, w)}}return &multiWriter{allWriters}}// 重写io.Writer的Write函数函数,本质上就是遍历数组,比较巧妙func (t *multiWriter) Write(p []byte) (n int, err error) {for _, w := range t.writers {n, err = w.Write(p)if err != nil {return}if n != len(p) {err = ErrShortWritereturn}}return len(p), nil}

使用方式如下:

func main() {f, err := os.OpenFile("log.log", os.O_CREATE|os.O_APPEND|os.O_RDWR, os.ModePerm)if err != nil {return}defer func() {f.Close()}()// 组合一下即可,os.Stdout代表标准输出流multiWriter := io.MultiWriter(os.Stdout, f)log.SetOutput(multiWriter)log.SetFlags(log.Ldate | log.Ltime | log.Lshortfile)log.Println("line1")log.Print("line2")log.Printf("line%d \n", 3)}

此时,再运行,则会同时输出到控制台和文件中。

/08/25 17:38:02 mod_unread_redis.go:42: line1/08/25 17:38:02 mod_unread_redis.go:43: line2/08/25 17:38:02 mod_unread_redis.go:44: line3

最后更新时间:-04-21

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。