golang 的log包使用起来挺简单,这里做一些简单介绍。
示例:
package mainimport ( "log")func main() { arr := []int{1, 2} log.Print("Print array ", arr, "\n") log.Println("Println array", arr) log.Printf("Printf array with item [%d,%d]\n", arr[0], arr[1])}
结果:
2018/12/14 18:42:02 Print array [1 2]
2018/12/14 18:42:02 Println array [1 2]
2018/12/14 18:42:02 Printf array with item [1,2]
log.Fatal 、log.Fatalln、log.Fatalf
示例:
log.Fatal("Fatal array ", arr, "\n") log.Fatalln("Fatalln array", arr) log.Fatalf("Fatalf array with item [%d,%d]\n", arr[0], arr[1])
对于 log.Fatal 接口,会先将日志内容打印到标准输出,接着调用系统的 os.exit(1) 接口退出程序并返回状态 1 。
在实际开发中要慎重,它导致整个系统退出,且不执行defer。
示例
package mainimport ( "fmt" "log" "net/http")func sayHelloHandler(w http.ResponseWriter, r *http.Request) { defer func() { fmt.Println("--first--") }() log.Fatalln("test for defer Fatal")}func main() { http.HandleFunc("/", sayHelloHandler) // 设置访问路由 log.Fatal(http.ListenAndServe(":8080", nil))}
当访问 http://127.0.0.1:8080/ 后,http 服务停止了,且defer没有调用。
log.SetOutput
将日志写到指定文件中
示例
package mainimport ( "log" "os")func main() { // 按照所需读写权限创建文件 f, err := os.OpenFile("filename.log", os.O_WRONLY|os.O_CREATE|os.O_APPEND, 0644) if err != nil { log.Fatal(err) } // 完成后延迟关闭 defer f.Close() //设置日志输出到 f log.SetOutput(f) //写入日志内容 log.Println("check to make sure it works")}
查看生成日志文件filename.log 内容
2018/12/14 18:56:55 check to make sure it works
log.Logger、log.New
先自定义Logger类型, log.Logger提供了一个New方法用来创建对象:
func New(out io.Writer, prefix string, flag int) *Logger
该函数一共有三个参数:
(1)输出位置out,是一个io.Writer对象,该对象可以是一个文件也可以是实现了该接口的对象。通常我们可以用这个来指定日志输出到哪个文件。
(2)prefix 我们在前面已经看到,就是在日志内容前面的东西。我们可以将其置为 “[Info]” 、 “[Warning]”等来帮助区分日志级别。
(3) flags 是一个选项,显示日志开头的东西,可选的值有:
Ldate = 1 << iota // 形如 2009/01/23 的日期Ltime // 形如 01:23:23 的时间Lmicroseconds // 形如 01:23:23.123123 的时间Llongfile // 全路径文件名和行号: /a/b/c/d.go:23 Lshortfile // 文件名和行号: d.go:23LstdFlags = Ldate | Ltime // 日期和时间
package mainimport ( "io" "io/ioutil" "log" "os")var ( Trace *log.Logger // 记录所有日志 Info *log.Logger // 重要的信息 Warning *log.Logger // 需要注意的信息 Error *log.Logger // 致命错误)func init() { file, err := os.OpenFile("filename.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666) if err != nil { log.Fatalln(err) } Trace = log.New(ioutil.Discard, "TRACE: ", log.Ltime|log.Lshortfile) Info = log.New(os.Stdout, "Info: ", log.Ltime|log.Lshortfile) Warning = log.New(os.Stdout, "Warning: ", log.Ltime|log.Lshortfile) Error = log.New(io.MultiWriter(file, os.Stderr), "Error", log.Ltime|log.Lshortfile)}func main() { Trace.Println("trace") Info.Println("info") Warning.Println("warning") Error.Println("Error")}
细心的朋友可能发现执行多次程序输出日志的顺序会有变化,这个主要是 os.Stderr和os.Stdout输出的不同引起的,这两个虽然都是输出到终端,但在默认情况下,stdout是行缓冲的,它的输出会放在一个buffer里面,只有到换行的时候,才会输出到屏幕。而stderr是无缓冲的,会直接输出的。参考:http://blog.sina.com.cn/s/blog_912673ce01013qq9.html
日志库logrus
logrus是在Github中star最多的go日志库,功能强大,性能不错。
安装:
go get -u github.com/sirupsen/logrus
实例
package mainimport ( "github.com/sirupsen/logrus" "os")// Create a new instance of the logger. You can have any number of instances.var log = logrus.New()func main() { // The API for setting attributes is a little different than the package level // exported logger. See Godoc. log.Out = os.Stdout //You could set this to any `io.Writer` such as a file file, err := os.OpenFile("logrus.log", os.O_CREATE|os.O_WRONLY, 0666) if err == nil { log.Out = file } else { log.Info("Failed to log to file, using default stderr") } log.WithFields(logrus.Fields{ "animal": "walrus", "size": 10, }).Info("A group of walrus emerges from the ocean")}
如果你对别的Go日志库感兴趣可以参考: