参考链接:
import (
"log"
)
func main() {
log.Print("Logging in Go!")
}
log模块的Fatal与Panic开头的function都会直接终止程序运行,这点需要注意。
log模块只有Print与Fatal、Panic三个level对应的函数,可以通过SetOutput函数定义输出目的地,如下为输出至文件的示例。
package main
import (
"log"
"os"
)
func main() {
file, err := os.OpenFile("info.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0644)
if err != nil {
log.Fatal(err)
}
defer file.Close()
log.SetOutput(file)
log.Print("Logging to a file in Go!")
}
go源生log包虽然可以用,但相比其他语言的源生log模块和各种定制框架还是弱了很多,uber家的zap是一款比较好的log框架,示例:
logger, _ := zap.NewProduction()
defer logger.Sync() // flushes buffer, if any
sugar := logger.Sugar()
sugar.Infow("failed to fetch URL",
// Structured context as loosely typed key-value pairs.
"url", url,
"attempt", 3,
"backoff", time.Second,
)
sugar.Infof("Failed to fetch URL: %s", url)
When performance and type safety are critical, use the Logger. It's even faster than the SugaredLogger and allocates far less, but it only supports structured logging.
推荐下述直接使用logger方法的写法,接收zapcore.Field类型输入,可以有0个或多个输入参数:
func main(){
logger, _ := zap.NewProduction()
defer logger.Sync()
url := `www.baidu.com`
logger.Warn("failed to fetch URL",
// Structured context as strongly typed Field values.
zap.String("url", url),
zap.Int("attempt", 3),
zap.Duration("backoff", time.Second),
)
}
Output:
{"level":"warn","ts":1616394834.0561035,"caller":"logtest/main.go:12","msg":"failed to fetch URL","url":"www.baidu.com","attempt":3,"backoff":1}
可以看出优点是可以打印出logger发生的代码行数,并且输出了结构化的日志。
我们可以通过封装zap来实现自己的log模块,但没必要因为看到一个比较好用的,就是pingcap家的log模块,用起来比较不错,Demo示例如下:
package main
import (
"fmt"
"github.com/pingcap/log"
"go.uber.org/zap"
"go.uber.org/zap/zapcore"
)
func main(){
fmt.Printf("%v
",log.GetLevel())
log.Debug(`This is a debug message.`, zap.String("lv", "debug"), zap.Int("no", 1))
log.Info(`This is a info message.`, zap.String("lv", "info"), zap.String("extra", "some extra msg"))
log.Warn(`This is a warning message.`, zap.String("lv", "warning"), zap.String("extra", "some extra msg"))
log.SetLevel(zapcore.DebugLevel)
fmt.Printf("%v
",log.GetLevel())
log.Debug(`This is a debug message.`, zap.String("lv", "debug"), zap.Int("no", 1))
}
output如下:

可以看到上述非常简洁,但功能强大,各个level的方法可接受多个zap类型的参数,最终打印出来的日志如上,每条日志都标识了发生的代码行数,每条日志的各个部分使用[]进行分隔。