您好,登錄后才能下訂單哦!
這篇“怎么在Go語言中使用日志包”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么在Go語言中使用日志包”文章吧。
讓我們來看一下日志文件的定義:
日志文件是記錄操作系統或其他軟件運行中發生的事件或通信軟件的不同用戶之間的消息的文件。記錄是保存日志的行為。
日志是開發人員的眼睛和耳朵,可以用來跟蹤、定位錯誤、調試和分析代碼,并監控應用程序的性能。在最簡單的情況下,消息被寫入單個日志文件。
正因為日志很重要,所以 Go 語言標準庫提供了 log
包,可以對日志做一些簡單的配置,我們可以定制一套自己的日志記錄器。
Golang 中的 log
包實現了簡單的 logging 包。它定義了一個類型、Logger 以及格式化輸出的方法。 它還具有預定義的“標準”記錄器,可通過輔助函數 Print[f|ln]
、Fatal[f|ln]
和 Panic[f|ln]
訪問,它們比手動創建記錄器更易于使用。
基本的日志項包括:前綴、日期時間戳、該日志由哪個源文件記錄的、源文件記錄日志所在行,最后是日志消息。讓我們來看一下簡單的使用 log
包:在除法運算時除 0 時的消息返回程序,而不是直接退出程序。
package main import ( "errors" "fmt" "log" ) func myDiv(x float64, y float64) (float64, error) { if y == 0 { return 0, errors.New("被除數不能為0") } return x / y, nil } func main() { var x float64 = 128.2 var y float64 res, err := myDiv(x, y) if err != nil { log.Print(err) // Print 寫到標準日志記錄器 } fmt.Println(res) }
運行該程序:
$ go run learninglog.go
2022/04/19 23:18:06 被除數不能為0
0
在上面的程序中,我們導入了三個包:errors
、fmt
、log
。
然后使用了 log
包中的 Print
函數:此時日志記錄器將寫入標準錯誤并打印每條記錄消息的日期和時間,這在一般情況下非常有用。每條日志消息在單獨的行上都有一個輸出:如果正在打印的消息沒有在新行結束,記錄器將添加一行。
另外,log
包中的 Fatal
函數在寫入日志消息后調用 os.Exit(1)
。
func main() { var x float64 = 128.2 var y float64 res, err := myDiv(x, y) if err != nil { log.Fatal(err) // 在調用 Print() 之后會接著調用 os.Exit(1) } fmt.Println(res) } // 2022/04/19 23:22:44 被除數不能為0 // exit status 1
而 Panic
函數在寫入日志消息后調用 panic
,除非程序執行 recover()
函數,否則會導致程序打印調用棧后終止。
func main() { var x float64 = 128.2 var y float64 res, err := myDiv(x, y) if err != nil { log.Panic(err) // Panic 會在調用 Print() 之后接著用 panic() } fmt.Println(res) }
運行結果:
2022/04/19 23:24:18 被除數不能為0
panic: 被除數不能為0
goroutine 1 [running]:
log.Panic({0xc000086f60?, 0xc000086f70?, 0x404f99?})
/usr/local/go/src/log/log.go:385 +0x65
main.main()
/home/wade/go/src/logLearning/learninglog.go:26 +0x65
exit status 2
由此可知,Print
系列函數才是寫日志消息的標準方法。
上述代碼中,只是簡單把日志消息打印到控制臺,這是遠遠不夠的,因為控制臺是實時的,如果關閉控制臺日志消息也就關閉了。
鑒于我們已經學習了 Go 語言如何讀取文件,所以就可以把日志消息存儲到一個文件中,把所有的日志存儲到該文件中。
package main import ( "errors" "fmt" "log" "os" ) func myDiv(x float64, y float64) (float64, error) { if y == 0 { return 0, errors.New("被除數不能為0") } return x / y, nil } func main() { var x float64 = 128.2 var y float64 res, exception := myDiv(x, y) file, err := os.OpenFile("info.log", os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0600) if err != nil { log.Fatal(err) } defer file.Close() // 關閉文件 log.SetOutput(file) log.Print(exception) fmt.Println(res) }
運行代碼:
$ go run learninglog.go
0
此外,我們會發現目錄中多了一個創建的 info.log
文件。打開文件,你會看到打印出類似下面的內容。
要想創建一個定制的日志記錄器,我們需要創建一個 Logger
類型的結構體,然后給每個日志記錄器配置一個輸出目的地、前綴和標志。而且每一個日志記錄器是多 goroutine 安全的,每一個 Logger
結構體都有一個互斥鎖,意味著多個 goroutine 可以同時調用來自同一個日志記錄器的這些函數,而不會有彼此間的寫沖突。來看一下 Logger
結構體的底層實現:
Logger結構體
// A Logger represents an active logging object that generates lines of // output to an io.Writer. Each logging operation makes a single call to // the Writer's Write method. A Logger can be used simultaneously from // multiple goroutines; it guarantees to serialize access to the Writer. type Logger struct { mu sync.Mutex // ensures atomic writes; protects the following fields prefix string // prefix on each line to identify the logger (but see Lmsgprefix) flag int // properties out io.Writer // destination for output buf []byte // for accumulating text to write }
然后我們來看一個示例程序:
package main import ( "io" "io/ioutil" "log" "os" ) var ( Trace *log.Logger // 記錄所有日志 Info *log.Logger // 重要的信息 Warning *log.Logger // 警告信息 Error *log.Logger // 錯誤信息 ) func init() { file, err := os.OpenFile("errors.txt", 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.Ldate|log.Ltime|log.Lshortfile) Info = log.New(os.Stdout, "Info: ", log.Ldate|log.Ltime|log.Lshortfile) Warning = log.New(os.Stdout, "Warning: ", log.Ldate|log.Ltime|log.Lshortfile) Error = log.New(io.MultiWriter(file, os.Stderr), "Error: ", log.Ldate|log.Ltime|log.Lshortfile) } func main() { Trace.Println("hello") Info.Println("Information") Warning.Println("Warning") Error.Println("Error") }
運行結果:
Info: 2022/04/20 00:37:34 learninglog.go:36: Information
Warning: 2022/04/20 00:37:34 learninglog.go:37: Warning
Error: 2022/04/20 00:37:34 learninglog.go:38: Error
使用 log
包的 New
函數,創建并初始化一個 Logger 類型的值,然后 New
函數返回新創建的值的地址。
New 函數
func New(out io.Writer, prefix string, flag int) *Logger { return &Logger{out: out, prefix: prefix, flag: flag }
New 函數的第一個參數 out
指定了日志要寫入的目的地,這個參數傳入的值必須實現了 io.Writer
接口
第二個參數 prefix
會在生成的每行日志的最開始出現
第三個參數 flag
定義日志包含哪些屬性
在本程序中:
Trace 日志記錄器使用了 ioutil
包里的 Discard 變量作為寫到的目的地,所有的 Writer 調用都不會有動作,但是會成功返回。當某個等級的日志不重要時,使用 Discard 變量可以禁用這個等級的日志。
日志記錄器 Info 和 Warning 都使用 stdout 作為日志輸出。
日志記錄去 Error 中的 New 函數第一個參數使用了 MultiWriter
函數,這個函數調用會返回一個 io.Writer
接口類型的值,這個值包含之前打開的文件 file,以及 stderr。這個函數是一個變參函數,可以接受任意個實現了 io.Writer
接口的值,所以會把所有傳入的 io.Writer
綁定在一起,當對這個返回值進行寫入時,會向所有綁在一起的 io.Writer
值做寫入。從而實現向多個 Writer 做輸出。這樣做的好處就是使用 Error 記錄器記錄日志時,輸出會同時寫到文件和 stderr 中。
以上就是關于“怎么在Go語言中使用日志包”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。