参考链接:
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类型的参数,最终打印出来的日志如上,每条日志都标识了发生的代码行数,每条日志的各个部分使用[]进行分隔。