golang内置了log包,实现简单的日志服务。通过调用log包的函数,可以实现简单的日志打印功能。
log包定义了Logger类型,该类型提供了一些格式化输出的方法。本包也提供了一个预定义的“标准”logger,可以通过调用函数Print系列(Print|Printf|Println)、Fatal系列(Fatal|Fatalf|Fatalln)、和Panic系列(Panic|Panicf|Panicln)来使用,比自行创建一个logger对象更容易使用,它们会将日志信息打印到终端界面
log包中有3个系列的日志打印函数,分别print系列、panic系列、fatal系列.
函数系列 | 说明 | 作用 |
---|---|---|
Print/Printf/Println | 单纯打印日志 | |
Panic | Panic/Panicf/Panicln | 打印日志,抛出panic异常 |
Fatal | Fatal/Fatalf/Fatalln | 打印日志,强制结束程序(os.Exit(1)),defer函数不会执行 |
log包主要提供了3类接口,分别是print系列、panic系列、fatal系列,对每一类接口其提供了3种调用方式,分别是“Xxxx、Xxxxln、Xxxxf”,基本与fmt
中的相关函数类似。
log.Print/Println/Printf函数只是单纯打印日志
实例演示:
package main
import "log"
func main() {
log.Print("my log")
log.Printf("my log %d", 100) // 格式化输出
name := "tom"
age := 20
log.Println(name, " ", age)
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
2022/07/12 17:27:16 my log
2022/07/12 17:27:16 my log 100
2022/07/12 17:27:16 tom 20
[Done] exited with code=0 in 1.118 seconds
基本使用与fmt
中的函数类似
log.Panic/Panicf/Panicln函数会打印出日志并且抛出panic异常,需要注意的是在panic之后声明的代码将不会执行。
实例演示:
package main
import (
"fmt"
"log"
)
func main() {
defer fmt.Println("发生了 panic错误!")
log.Print("my log")
log.Panic("my panic")
fmt.Println("运行结束。。。")
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
2022/07/12 17:31:48 my log
2022/07/12 17:31:48 my panic
发生了 panic错误!
panic: my panic
goroutine 1 [running]:
log.Panic({0xc00007ff30?, 0x60?, 0x6e7be0?})
c:/go/src/log/log.go:385 +0x65
main.main()
c:/Users/Mechrevo/Desktop/go_pro/test.go:11 +0xc5
exit status 2
[Done] exited with code=1 in 1.013 seconds
可见输出了log.Print
和log.Panic
中的内容,然后再panic之前的defer函数被调用并输出,而log.Panic
之后的fmt.Println
并没有被调用输出,可见log.Panic
抛出panic异常之后的代码是不会被调用的。
log.Panicf/Panicln用法与2.1中的Println/Printf函数类似,此处不再赘述。
对于log.Fatal
接口,会将日志内容打印输出,接着调用系统的os.Exit(1)
接口,强制退出程序并返回状态1,但是有一点需要注意的是,由于直接调用系统os接口退出,defer函数不会调用。
实例演示:
package main
import (
"fmt"
"log"
)
func main() {
defer fmt.Println("defer。。。")
log.Print("my log")
log.Fatal("my fatal")
fmt.Println("运行结束。。。")
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
2022/07/12 17:40:04 my log
2022/07/12 17:40:04 my fatal
exit status 1
[Done] exited with code=1 in 0.975 seconds
可见并没有调用defer函数。
log.Fatalf/Fatalln用法与2.1中的Println/Printf函数类似,此处不再赘述。
默认情况下log只会打印出时间,但是实际情况下我们还需要获取文件名,行号等信息,log包提供给我们定制的接口。
log包提供两个标准log配置的相关方法:
方法 | 说明 |
---|---|
func Flags() int | 返回标准log输出配置 |
func SetFlags(flag int) | 设置标准log输出配置 |
const (
// 控制输出日志信息的细节,不能控制输出的顺序和格式。
// 输出的日志在每一项后会有一个冒号分隔,例如2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message
Ldate = 1 << iota // 日期,2009/01/23
Ltime // 时间,01:23:23
Lmicroseconds // 微秒级别的时间,01:23:23.123123(用于增强Ltime位)
Llongfile // 文件全路径名+行号,/a/b/c/d.go:23
Lshortfile // 文件名+行号,d.go:23(会覆盖掉Llongfile)
LUTC // 使用UTC时间
LstdFlags = Ldate | Ltime // 标准logger的初始值
)
package main
import (
"fmt"
"log"
)
func main() {
i := log.Flags()
fmt.Printf("i: %v\n", i)
log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
log.Print("my log")
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
i: 3
2022/07/12 17:59:29 c:/Users/Mechrevo/Desktop/go_pro/test.go:12: my log
[Done] exited with code=0 in 1.102 seconds
log包提供两个日志前缀配置的相关函数:
方法 | 说明 |
---|---|
func Prefix() string | 返回日志的前缀配置 |
func SetPrefix(prefix string) | 设置日志前缀 |
实例演示:
package main
import (
"fmt"
"log"
)
func main() {
s := log.Prefix()
fmt.Printf("s: %v\n", s)
log.SetPrefix("[MyLog] ")
s = log.Prefix()
fmt.Printf("s: %v\n", s)
log.Print("my log...")
}
运行结果:
[Running] go run "c:\Users\Mechrevo\Desktop\go_pro\test.go"
s:
s: [MyLog]
[MyLog] 2022/07/12 18:00:55 my log...
[Done] exited with code=0 in 0.977 seconds
前面介绍的都是将日志输出到控制台上,golang的log包还支持将日志输出到文件中,log包提供了func SetOutput(w io.Writer)
函数,将日志输出到文件中。
实例演示:
package main
import (
"log"
"os"
)
func main() {
f, err := os.OpenFile("a.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Panic("打开日志文件异常")
}
log.SetOutput(f)
log.Print("my log...")
}
运行结果:
日志输出到当前目录下 a.log文件中
2022/07/12 18:02:20 my log...
log包中提供了func New(out io.Writer, prefix string, flag int) *Logger
函数来实现自定义logger。从效果上来看,就是标准日志配置、日志前缀配置、日志输出位置配置整合到一个函数中,使日志配置不在那么繁琐。
实例演示:
package main
import (
"log"
"os"
)
var logger *log.Logger
func init() {
logFile, err := os.OpenFile("a.log", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0644)
if err != nil {
log.Panic("打开日志文件异常")
}
logger = log.New(logFile, "[Mylog]", log.Ldate|log.Ltime|log.Lshortfile)
}
func main() {
logger.Println("自定义logger")
}
运行结果:
日志输出到当前目录下 a.log文件中
[Mylog]2022/07/12 18:06:21 test.go:19: 自定义logger