溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

怎么在Go語言中使用日志包

發(fā)布時間:2022-04-20 15:17:35 來源:億速云 閱讀:147 作者:iii 欄目:開發(fā)技術

這篇“怎么在Go語言中使用日志包”文章的知識點大部分人都不太理解,所以小編給大家總結了以下內容,內容詳細,步驟清晰,具有一定的借鑒價值,希望大家閱讀完這篇文章能有所收獲,下面我們一起來看看這篇“怎么在Go語言中使用日志包”文章吧。

讓我們來看一下日志文件的定義:

日志文件是記錄操作系統(tǒng)或其他軟件運行中發(fā)生的事件或通信軟件的不同用戶之間的消息的文件。記錄是保存日志的行為。

日志是開發(fā)人員的眼睛和耳朵,可以用來跟蹤、定位錯誤、調試和分析代碼,并監(jiān)控應用程序的性能。在最簡單的情況下,消息被寫入單個日志文件。

Go 語言標準庫之log 包

正因為日志很重要,所以 Go 語言標準庫提供了 log 包,可以對日志做一些簡單的配置,我們可以定制一套自己的日志記錄器。

Golang 中的 log 包實現(xiàn)了簡單的 logging 包。它定義了一個類型、Logger 以及格式化輸出的方法。 它還具有預定義的“標準”記錄器,可通過輔助函數(shù) Print[f|ln]、Fatal[f|ln]Panic[f|ln] 訪問,它們比手動創(chuàng)建記錄器更易于使用。

基本的日志項包括:前綴、日期時間戳、該日志由哪個源文件記錄的、源文件記錄日志所在行,最后是日志消息。讓我們來看一下簡單的使用 log 包:在除法運算時除 0 時的消息返回程序,而不是直接退出程序。

package main
import (
"errors"
"fmt"
"log"
)
func myDiv(x float64, y float64) (float64, error) {
if y == 0 {
return 0, errors.New("被除數(shù)不能為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 被除數(shù)不能為0
0

在上面的程序中,我們導入了三個包:errorsfmt、log

然后使用了 log 包中的 Print 函數(shù):此時日志記錄器將寫入標準錯誤并打印每條記錄消息的日期和時間,這在一般情況下非常有用。每條日志消息在單獨的行上都有一個輸出:如果正在打印的消息沒有在新行結束,記錄器將添加一行。

另外,log 包中的 Fatal 函數(shù)在寫入日志消息后調用 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 被除數(shù)不能為0
// exit status 1

Panic 函數(shù)在寫入日志消息后調用 panic,除非程序執(zhí)行 recover() 函數(shù),否則會導致程序打印調用棧后終止。

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 被除數(shù)不能為0
panic: 被除數(shù)不能為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 系列函數(shù)才是寫日志消息的標準方法。

如何將日志消息存儲在 Go 中的文件中

上述代碼中,只是簡單把日志消息打印到控制臺,這是遠遠不夠的,因為控制臺是實時的,如果關閉控制臺日志消息也就關閉了。

鑒于我們已經學習了 Go 語言如何讀取文件,所以就可以把日志消息存儲到一個文件中,把所有的日志存儲到該文件中。

package main
import (
"errors"
"fmt"
"log"
"os"
)
func myDiv(x float64, y float64) (float64, error) {
if y == 0 {
return 0, errors.New("被除數(shù)不能為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

此外,我們會發(fā)現(xiàn)目錄中多了一個創(chuàng)建的 info.log 文件。打開文件,你會看到打印出類似下面的內容。

定制你的日志記錄器

要想創(chuàng)建一個定制的日志記錄器,我們需要創(chuàng)建一個 Logger 類型的結構體,然后給每個日志記錄器配置一個輸出目的地、前綴和標志。而且每一個日志記錄器是多 goroutine 安全的,每一個 Logger 結構體都有一個互斥鎖,意味著多個 goroutine 可以同時調用來自同一個日志記錄器的這些函數(shù),而不會有彼此間的寫沖突。來看一下 Logger 結構體的底層實現(xiàn):

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 函數(shù),創(chuàng)建并初始化一個 Logger 類型的值,然后 New 函數(shù)返回新創(chuàng)建的值的地址。

New 函數(shù)

func New(out io.Writer, prefix string, flag int) *Logger {
return &Logger{out: out, prefix: prefix, flag: flag
}
  • New 函數(shù)的第一個參數(shù) out 指定了日志要寫入的目的地,這個參數(shù)傳入的值必須實現(xiàn)了 io.Writer 接口

  • 第二個參數(shù) prefix 會在生成的每行日志的最開始出現(xiàn)

  • 第三個參數(shù) flag 定義日志包含哪些屬性

在本程序中:

  • Trace 日志記錄器使用了 ioutil 包里的 Discard 變量作為寫到的目的地,所有的 Writer 調用都不會有動作,但是會成功返回。當某個等級的日志不重要時,使用 Discard 變量可以禁用這個等級的日志。

  • 日志記錄器 Info 和 Warning 都使用 stdout 作為日志輸出。

  • 日志記錄去 Error 中的 New 函數(shù)第一個參數(shù)使用了 MultiWriter 函數(shù),這個函數(shù)調用會返回一個 io.Writer 接口類型的值,這個值包含之前打開的文件 file,以及 stderr。這個函數(shù)是一個變參函數(shù),可以接受任意個實現(xiàn)了 io.Writer 接口的值,所以會把所有傳入的 io.Writer 綁定在一起,當對這個返回值進行寫入時,會向所有綁在一起的 io.Writer 值做寫入。從而實現(xiàn)向多個 Writer 做輸出。這樣做的好處就是使用 Error 記錄器記錄日志時,輸出會同時寫到文件和 stderr 中

以上就是關于“怎么在Go語言中使用日志包”這篇文章的內容,相信大家都有了一定的了解,希望小編分享的內容對大家有幫助,若想了解更多相關的知識內容,請關注億速云行業(yè)資訊頻道。

向AI問一下細節(jié)

免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng)、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯(lián)系站長郵箱:is@yisu.com進行舉報,并提供相關證據(jù),一經查實,將立刻刪除涉嫌侵權內容。

AI