Golang中使用log(一):Golang 標準庫提供的Log

Golang的標準庫提供了log的機制,可是該模塊的功能較爲簡單(看似簡單,其實他有他的設計思路)。不過比手寫fmt. Printxxx仍是強不少的。至少在輸出的位置作了線程安全的保護。其官方手冊見Golang log (天朝的牆你們懂的)。這裏給出一個簡單使用的例子:golang

package main
import (
    "log"
)
func main(){
    log.Fatal("Come with fatal,exit with 1 \n")
}

編譯運行後,會看到程序打印了 Come with fatal,exit with 1 而後就退出了,若是用 echo $? 查看退出碼,會發現是 「1」。安全

通常接口

Golang's log模塊主要提供了3類接口。分別是 「Print 、Panic 、Fatal 」。固然是用前先包含log包。markdown

import(
    "log"
)

爲了方即是用,Golang和Python同樣,在提供接口時,提供一個簡單的包級別的使用接口。不一樣於Python,其輸出默認定位到標準錯誤 能夠經過SetOutput 進行修改。ide

對每一類接口其提供了3中調用方式,分別是 "Xxxx 、 Xxxxln 、Xxxxf" 好比對於Print就有:函數

log.Print
log.Printf
log.Println
  • log.Print :表示其參數的調用方式和 fmt.Print 是相似的,即輸出對象而不用給定特別的標誌符號。學習

  • log.Printf : 表示其參數的調用方式和 fmt.Printf 是相似的,便可以用C系列的格式化標誌表示輸出對象的類型,具體類型表示 能夠參考fmt.Printf的文檔spa

  • log.Println: 表示其調用方式和fmt.Println 相似,其和log.Print基本一致,僅僅是在輸出的時候多輸出一個換行線程

這裏是以 「Print」來具體說明的,對於「Panic」和「Fatal」也是同樣的。下面再以"Print"爲例,看下調用方式:debug

package main
import (
    "log"
)
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])
}

會獲得以下結果:設計

2014/05/02 12:27:19 Print array [2 3]
2014/05/02 12:27:19 Println array [2 3]
2014/05/02 12:27:19 Printf array with item [2,3]

輸出中的日期和時間是默認的格式,若是直接調用簡單接口,其格式是固定的,能夠經過 SetFlags 方法進行修改,同時這裏輸出 內容的(傳個log.Print的內容)前面和時間的後面是空的,這也是默認的行爲,咱們能夠經過添加前綴來表示其是一條"Warnning" 或者是一條"Debug"日誌。經過使用 SetPrefix 能夠設置該前綴。

SetOutputSetFlagsSetPrefix 這裏關係不大,先不解釋,留到後面介紹Logger類型中一併解釋。

看完了 log.PrintXxx 接口,咱們再來看下 log.FatalXxx 接口,咱們以 log.Fatal 爲例介紹其功能。如最開始看到的例子, 在調用 log.Fatal 接口後,會先將日誌內容打印到標準輸出,接着調用系統的 os.exit(1) 接口,退出程序返回狀態爲 「1」

比較複雜的是 log.PanicXxx ,看該函數的說明,其至關於再把日誌內容刷到標準錯誤後調用 panic 函數(不清楚Golan的defer-recover-panic機制能夠Golang Blog去學習一下)。這裏舉個經常使用的例子:

package main
import (
    "log"
    "fmt"
)
func main(){
    defer func(){
        if e:= recover();e!= nil {
            fmt.Println("Just comming recover")
            fmt.Println("e from recover is :",e)
            fmt.Println("After recover")
        }
    }()
    arr := []int {2,3}
    log.Panic("Print array ",arr,"\n")
}

結果爲:

2014/05/03 13:52:42 Print array [2 3]
Just comming recover
e from recover is : Print array [2 3]
After recover

從結果咱們能夠看出,是先將日誌刷入標準輸出,而後經過defer裏面的recover進行捕獲panic的內容。

自定義Logger類型

理清了「Print 、Panic 、Fatal 」後咱們就好介紹 log.Logger 類型了。該類型提供了一個New方法用來建立對象。

func New(out io.Writer, prefix string, flag int) *Logger

其初始化條件分別是日誌寫入的位置 out ,日誌的前綴內容 prefix ,以及日誌的內容flag。能夠經過上面介紹的 SetOutputSetFlagsSetPrefix 依次對其進行設置。

  • 輸出位置out,是一個io.Writer對象,該對象能夠是一個文件也能夠是實現了該接口的對象。一般咱們能夠用這個來指定 其輸出到哪一個文件

  • prefix 咱們在前面已經看到,就是在日誌內容前面的內容。咱們能夠將其置爲 "[Info]" 、 "[Warning]"等來幫助區分日誌 級別。

  • flags 較爲迷惑,其實際上就是一個選項,可選的值有:

Ldate         = 1 << iota     // the date: 2009/01/23 形如 2009/01/23 的日期
Ltime                         // the time: 01:23:23   形如 01:23:23   的時間
Lmicroseconds                 // microsecond resolution: 01:23:23.123123.  形如01:23:23.123123   的時間
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 // 日期和時間

表示在日誌內容開頭,咱們暫且稱之爲日誌擡頭,打印出相關內容。對於上面的默認格式就是 LstdFlags 打印出日期和時間。

該方法還定義瞭如上一些同名方法。

func (l *Logger) Print(v ...interface{})
func (l *Logger) Printf(format string, v ...interface{})
func (l *Logger) Println(v ...interface{})
func (l *Logger) Fatal(v ...interface{})
func (l *Logger) Fatalf(format string, v ...interface{})
func (l *Logger) Fatalln(v ...interface{})
func (l *Logger) Panic(v ...interface{})
func (l *Logger) Panicf(format string, v ...interface{})
func (l *Logger) Panicln(v ...interface{})
func (l *Logger) Flags() int
func (l *Logger) Prefix() string
func (l *Logger) SetFlags(flag int)
func (l *Logger) SetPrefix(prefix string)

其中 「Print 、Panic 、Fatal 」 系列函數和以前介紹的同樣,Flags和Prefix分別能夠得到log.Logger當前的日誌擡頭和前綴。 SetFlags ,SetPrefix 則能夠用來設置日誌擡頭和前綴。

使用實例

最後我看有log模塊將debug日誌打印到文件的實例。

package main
import (
    "log"
    "os"
)
func main(){
    fileName := "xxx_debug.log"
    logFile,err  := os.Create(fileName)
    defer logFile.Close()
    if err != nil {
        log.Fatalln("open file error !")
    }
    debugLog := log.New(logFile,"[Debug]",log.Llongfile)
    debugLog.Println("A debug message here")
    debugLog.SetPrefix("[Info]")
    debugLog.Println("A Info Message here ")
    debugLog.SetFlags(debugLog.Flags() | log.LstdFlags)
    debugLog.Println("A different prefix")
}

運行後打開日誌文件咱們能夠看到相應的日誌內容

相關文章
相關標籤/搜索