一、快速使用
Golang的log包短小精悍,可以非常轻松的实现日志打印转存功能。不用多说,log支持并发操作(即协程安全-相对于JAVA中的线程安全而言),其结构定义如下:
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包定义了一些日志格式标志:
// These flags define which text to prefix to each log entry generated by the Logger. const ( // Bits or'ed together to control what's printed. There is no control over the // order they appear (the order listed here) or the format they present (as // described in the comments). A colon appears after these items: // 2009/01/23 01:23:23.123123 /a/b/c/d.go:23: message Ldate = 1 << iota // the date: 2009/01/23 Ltime // the time: 01:23:23 Lmicroseconds // microsecond resolution: 01:23:23.123123. assumes Ltime. Llongfile // full file name and line number: /a/b/c/d.go:23 Lshortfile // final file name element and line number: d.go:23. overrides Llongfile LstdFlags = Ldate | Ltime // initial values for the standard logger )
上述这些标志可以在创建Logger对象时指定(通过下面的New函数创建),也可以通过Logger.setFlat()方法动态指定。
Logger对象通过函数New创建
// New creates a new Logger. The out variable sets the // destination to which log data will be written. // The prefix appears at the beginning of each generated log line. // The flag argument defines the logging properties. func New(out io.Writer, prefix string, flag int) *Logger { return &Logger{out: out, prefix: prefix, flag: flag} }
log包已默认提供了一个日志对象,并封装了包级别的常用函数,该对象将日志信息输出到标准输出设备中(开箱即用)。
var std = New(os.Stderr, "", LstdFlags) // 日志中只使用的flag为LstdFlags,即只输出日期
如果只是想输出到终端而不保存到文件等其它地方时,可以直接通过log.Xxxx()方式直接调用,因为这些包级别的函数只是对std对象相关方法的简单封装,如println函数定义如下:
// Println calls Output to print to the standard logger. // Arguments are handled in the manner of fmt.Println. func Println(v ...interface{}) { std.Output(2, fmt.Sprintln(v...)) }
二、Logger对象方法使用说明
Logger对象提供了如下几个方法:
func (l *Logger) Output(calldepth int, s string) error ; // 真正负责日志打印的方法,其它级别的打印方法都将会调用它 // Println calls l.Output to print to the logger. // Arguments are handled in the manner of fmt.Println. func (l *Logger) Println(v ...interface{}) { // 一般信息打印方法,相当于JAVA中log的info级别 l.Output(2, fmt.Sprintln(v...)) } // Panicln is equivalent to l.Println() followed by a call to panic(). func (l *Logger) Panicln(v ...interface{}) { // 业务异常时使用的方法,该方法会抛出异常,调用方可以用recover捕获,相当于JAVA的ERROR级别(JAVA不会自动抛异常) s := fmt.Sprintln(v...) l.Output(2, s) panic(s) // 通过panic抛出异常,只有上层业务没捕获异常时,程序才会异常中止并退出, } // Fatalln is equivalent to l.Println() followed by a call to os.Exit(1). func (l *Logger) Fatalln(v ...interface{}) { l.Output(2, fmt.Sprintln(v...)) os.Exit(1) // 调用该方法会中止应用程序并直接退出 }
使用例子1
package main
import (
"log"
"os"
"io/ioutil"
"io"
)
var (
Trace *log.Logger // 记录所有日志
Info *log.Logger // 重要的信息
Warning *log.Logger // 需要注意的信息
Error *log.Logger // 致命错误
)
func init() {
file, err := os.OpenFile("file", os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0666)
if err != nil {
log.Fatalln("Failed to open error log file:", 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("I have something standard to say")
Info.Println("Special Information")
Warning.Println("There is something you need to know about")
Error.Println("Something has failed")
}
使用例子2
package main
import (
"bytes"
"fmt"
"log"
"io"
"io/ioutil"
"os"
)
type Logger struct {
// contains filtered or unexported fields
}
var (
Trace *log.Logger
Info *log.Logger
Warning *log.Logger
Error *log.Logger
)
func Init( traceHandle io.Writer, infoHandle io.Writer,
warningHandle io.Writer, errorHandle io.Writer)(Trace,Info,Warning,Error *log.Logger) {
Trace = log.New(traceHandle,"TRACE: ", log.Ldate|log.Ltime|log.Lshortfile)
Info = log.New(infoHandle, "INFO: ", log.Ldate|log.Ltime|log.Lshortfile)
Warning = log.New(warningHandle, "WARNING: ", log.Ldate|log.Ltime|log.Lshortfile)
Error = log.New(errorHandle, "ERROR: ", log.Ldate|log.Ltime|log.Lshortfile)
// Trace.Println("XXXXXXXXXXXX")
return //Trace,Info,Warning,Error
}
func test_log2(){
Trace,Info,Warning,Error :=Init(ioutil.Discard, os.Stdout, os.Stdout, os.Stderr)
Trace.Println("I have something standard to say")
Info.Println("Special Information")
Warning.Println("There is something you need to know about")
Error.Println("Something has failed")
}
func test_log1(){
var buf bytes.Buffer
logger := log.New(&buf, "logger: ", log.Lshortfile|log.Ldate)
logger.Print("Hello, log file!")
fmt.Print(&buf)
}
func main() {
test_log1()
test_log2()
}
更多参考