一、了解一些概念
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...)) }
二、如何將log 寫入到指定的文件中
方法一
package main import ( "log" "os" "time" ) func init() { file := "./" +"log"+ ".txt" logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766) if err != nil { panic(err) } log.SetOutput(logFile) // 將文件設置為log輸出的文件 log.SetPrefix("[log]") log.SetFlags(log.LstdFlags | log.Lshortfile | log.LUTC) return } func main() { log.Println("Hello logs!") // log 還是可以作為輸出的前綴 return }
方法二
package main import ( "log" "os" "time" ) var loger *log.Logger func init() { file := "./" + time.Now().Format("20180102") + ".txt" logFile, err := os.OpenFile(file, os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766) if err != nil { panic(err) } loger = log.New(logFile, "[qSkiptool]",log.LstdFlags | log.Lshortfile | log.LUTC) // 將文件設置為loger作為輸出 return } func main() { loger.Println("Hello logs") // 使用的時候,需要采用loger作為輸出的前 return }