内容简介:log支持并发操作。其结构定义如下:• log.Print:打印日志,和fmt.包没什么区别,只是加上了上面的日志格式• log.Fatal :,会先将日志内容打印到标准输出,接着调用系统的os.exit(1) 接口,退出程序并返回状态 1 。但是有一点需要注意,由于是直接调用系统接口退出,defer函数不会被调用。
一、log日志包
log支持并发操作。其结构定义如下:
type Logger struct {
mu sync.Mutex // ensures atomic writes; protects the following fields
prefix string // prefix to write at beginning of each line // ⽇志⾏前缀
flag int // properties // ⽇志打印格式标志,⽤于指定每⾏⽇志的打印格式
out io.Writer // destination for output // ⽤于指定⽇志输出位置,理论上可以是任务地⽅,只要实现了io.Writer接⼝就⾏
buf []byte // for accumulating text to write // ⽇志内容
}
log基本日志格式
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:23 LstdFlags = Ldate | Ltime // ⽇期和时间
(1)Golang's log模块主要提供了3类接口。分别是 “Print 、Panic 、Fatal ”,对每一类接口其提供了3中调用方式,分别是 "Xxxx 、Xxxxln 、Xxxxf",基本和fmt中的相关函数类似。
• log.Print:打印日志,和fmt.包没什么区别,只是加上了上面的日志格式
• log.Fatal :,会先将日志内容打印到标准输出,接着调用系统的os.exit(1) 接口,退出程序并返回状态 1 。但是有一点需要注意,由于是直接调用系统接口退出,defer函数不会被调用。
• log.Panic:该函数把日志内容刷到标准错误后调用 panic 函数,
demo
package main
import (
"fmt"
"log"
)
//fatal
func testDeferfatal() {
defer func() {
fmt.Println("--first--")
}()
log.Fatalln("test for defer Fatal")
}
//panic
func testDeferpanic() {
defer func() {
fmt.Println("--first--")
if err := recover(); err != nil {
fmt.Println(err)
}
}()
log.Panicln("test for defer Panic")
defer func() {
fmt.Println("--second--")
}()
}
func main() {
arr := []int{2, 3}
log.Print("Print array ", arr, "\n")
log.Println("Println array", arr)
log.Printf("Printf array with item [%d,%d]\n", arr[0], arr[1])
testDeferpanic()
testDeferfatal()
}
输出为
2018/12/17 21:28:33 Print array [2 3]
2018/12/17 21:28:33 Println array [2 3]
2018/12/17 21:28:33 Printf array with item [2,3]
2018/12/17 21:28:33 test for defer Panic
--first--
test for defer Panic
2018/12/17 21:28:33 test for defer Fatal
exit status 1
(2)你也可以自定义Logger类型
log.Logger提供了一个New方法用来创建对象
函数原型
func New(out io.Writer, prefix string, flag int) *Logger
①输出位置out,是一个io.Writer对象,该对象可以是一个文件也可以是实现了该接口的对象。通常我们可以用这个来指定日志输出到哪个文件
②prefix 我们在前面已经看到,就是在日志内容前面的东西。我们可以将其置为 "[Info]" 、 "[Warning]"等来帮助区分日志级别。
③flags 是一个选项,显示日志开头的东西,可选的值见前面所述
demo
func main() {
fileName := "/Users/zt/Desktop/Info_First.log"//路径+文件名
logFile, err := os.Create(fileName)
defer logFile.Close()
if err != nil {
log.Fatalln("open file error")
}
debugLog := log.New(logFile, "[Info]", log.Llongfile)
debugLog.Println("A Info message here")
debugLog.SetPrefix("[Debug]")
debugLog.Println("A Debug Message here ")
}
二、Zap日志包使用
uber开源的高性能日志库
go get go.uber.org/zap
demo
func panic() {
if err := recover(); err != nil {
fmt.Println(err)
}
}
func main() {
url := "Hello"
logger, _ := zap.NewProduction()
//logger, _ := zap.NewDevelopment()
defer panic()
//Sync刷新任何缓冲的日志条目。
defer logger.Sync()
logger.Info("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
logger.Warn("debug log", zap.String("level", url))
logger.Error("Error Message", zap.String("error", url))
logger.Panic("Panic log", zap.String("level", url))
}
(1)通过HTTP接口动态的改变日志级别
demo
func main() {
alevel := zap.NewAtomicLevel()
http.HandleFunc("/handle/level", alevel.ServeHTTP)
go func() {
if err := http.ListenAndServe(":9090", nil); err != nil {
panic(err)
}
}()
// 默认是Info级别
logcfg := zap.NewProductionConfig()
logcfg.Level = alevel
logger, err := logcfg.Build()
if err != nil {
fmt.Println("err", err)
}
defer logger.Sync()
for i := 0; i < 1000; i++ {
time.Sleep(1 * time.Second)
logger.Debug("debug log", zap.String("level", alevel.String()))
logger.Info("Info log", zap.String("level", alevel.String()))
}
}
查看日志级别
curl http://localhost:9090/handle/level
输出
调整日志级别(可选值 “debug” “info” “warn” “error” 等)
curl -XPUT --data '{"level":"debug"}' http://localhost:9090/handle/level
输出
当然也可以使用之前在Gin说过的工具RESTClient来模拟,
(2)将日志进行序列化文件:lumberjack
支持文件按大小或者时间归档
GitHub地址: https://github.com/natefinch/lumberjack
go get github.com/natefinch/lumberjack
package main
import (
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
lumberjack "gopkg.in/natefinch/lumberjack.v2"
)
func initLogger(logpath string, loglevel string) *zap.Logger {
hook := lumberjack.Logger{
Filename: logpath, // ⽇志⽂件路径
MaxSize: 1024, // megabytes
MaxBackups: 3, // 最多保留3个备份
MaxAge: 7, //days
Compress: true, // 是否压缩 disabled by default
}
w := zapcore.AddSync(&hook)
var level zapcore.Level
switch loglevel {
case "debug":
level = zap.DebugLevel
case "info":
level = zap.InfoLevel
case "error":
level = zap.ErrorLevel
default:
level = zap.InfoLevel
}
encoderConfig := zap.NewProductionEncoderConfig()
encoderConfig.EncodeTime = zapcore.ISO8601TimeEncoder
core := zapcore.NewCore(
zapcore.NewConsoleEncoder(encoderConfig),
w,
level,
)
logger := zap.New(core)
logger.Info("DefaultLogger init success")
return logger
}
func main() {
logger := initLogger("all.log", "info")
logger.Info("test log", zap.Int("line", 47))
logger.Warn("testlog", zap.Int("line", 47))
}
在当前文件夹下的all.log
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 【每日笔记】【Go学习笔记】2019-01-04 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-02 Codis笔记
- 【每日笔记】【Go学习笔记】2019-01-07 Codis笔记
- Golang学习笔记-调度器学习
- Vue学习笔记(二)------axios学习
- 算法/NLP/深度学习/机器学习面试笔记
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
Paradigms of Artificial Intelligence Programming
Peter Norvig / Morgan Kaufmann / 1991-10-01 / USD 77.95
Paradigms of AI Programming is the first text to teach advanced Common Lisp techniques in the context of building major AI systems. By reconstructing authentic, complex AI programs using state-of-the-......一起来看看 《Paradigms of Artificial Intelligence Programming》 这本书的介绍吧!