欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

如何在?Go語(yǔ)言中使用日志包

 更新時(shí)間:2022年04月20日 12:11:33   作者:宇宙之一粟  
這篇文章主要介紹了如何在?Go語(yǔ)言中使用日志包,日志文件就是一種快速找到這些?bug,更好地了解程序工作狀態(tài)的方法,下文基于go語(yǔ)言介紹該詳細(xì)需要的小伙伴可以參考一下

引言:

在我們的日常編程中,日志很重要。只要是我們寫(xiě)代碼,就有可能出現(xiàn) Bug。日志文件就是一種快速找到這些 bug,更好地了解程序工作狀態(tài)的方法。

讓我們來(lái)看一下日志文件的定義:

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

日志是開(kāi)發(fā)人員的眼睛和耳朵,可以用來(lái)跟蹤、定位錯(cuò)誤、調(diào)試和分析代碼,并監(jiān)控應(yīng)用程序的性能。在最簡(jiǎn)單的情況下,消息被寫(xiě)入單個(gè)日志文件。

Go 語(yǔ)言標(biāo)準(zhǔn)庫(kù)之log 包

正因?yàn)槿罩竞苤匾?,所?Go 語(yǔ)言標(biāo)準(zhǔn)庫(kù)提供了 ??log?? 包,可以對(duì)日志做一些簡(jiǎn)單的配置,我們可以定制一套自己的日志記錄器。

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

基本的日志項(xiàng)包括:前綴、日期時(shí)間戳、該日志由哪個(gè)源文件記錄的、源文件記錄日志所在行,最后是日志消息。讓我們來(lái)看一下簡(jiǎn)單的使用 ??log?? 包:在除法運(yùn)算時(shí)除 0 時(shí)的消息返回程序,而不是直接退出程序。

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 寫(xiě)到標(biāo)準(zhǔn)日志記錄器
}
fmt.Println(res)
}

運(yùn)行該程序:

$ go run learninglog.go
2022/04/19 23:18:06 被除數(shù)不能為0
0

在上面的程序中,我們導(dǎo)入了三個(gè)包:??errors?? 、??fmt??、??log?? 。

然后使用了 ??log?? 包中的 ??Print?? 函數(shù):此時(shí)日志記錄器將寫(xiě)入標(biāo)準(zhǔn)錯(cuò)誤并打印每條記錄消息的日期和時(shí)間,這在一般情況下非常有用。每條日志消息在單獨(dú)的行上都有一個(gè)輸出:如果正在打印的消息沒(méi)有在新行結(jié)束,記錄器將添加一行。

另外,??log?? 包中的 ??Fatal?? 函數(shù)在寫(xiě)入日志消息后調(diào)用 ??os.Exit(1)??。

func main() {
var x float64 = 128.2
var y float64
res, err := myDiv(x, y)
if err != nil {
log.Fatal(err) // 在調(diào)用 Print() 之后會(huì)接著調(diào)用 os.Exit(1)
}
fmt.Println(res)
}
// 2022/04/19 23:22:44 被除數(shù)不能為0
// exit status 1

而 ??Panic?? 函數(shù)在寫(xiě)入日志消息后調(diào)用 ??panic??,除非程序執(zhí)行 ??recover()?? 函數(shù),否則會(huì)導(dǎo)致程序打印調(diào)用棧后終止。

func main() {
var x float64 = 128.2
var y float64
res, err := myDiv(x, y)
if err != nil {
log.Panic(err) // Panic 會(huì)在調(diào)用 Print() 之后接著用 panic()
}
fmt.Println(res)
}

運(yùn)行結(jié)果:

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ù)才是寫(xiě)日志消息的標(biāo)準(zhǔn)方法。

如何將日志消息存儲(chǔ)在 Go 中的文件中

上述代碼中,只是簡(jiǎn)單把日志消息打印到控制臺(tái),這是遠(yuǎn)遠(yuǎn)不夠的,因?yàn)榭刂婆_(tái)是實(shí)時(shí)的,如果關(guān)閉控制臺(tái)日志消息也就關(guān)閉了。

鑒于我們已經(jīng)學(xué)習(xí)了 Go 語(yǔ)言如何讀取文件,所以就可以把日志消息存儲(chǔ)到一個(gè)文件中,把所有的日志存儲(chǔ)到該文件中。

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() // 關(guān)閉文件
log.SetOutput(file)
log.Print(exception)
fmt.Println(res)
}

運(yùn)行代碼:

$ go run learninglog.go
0

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

定制你的日志記錄器

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

Logger結(jié)構(gòu)體

// 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
}

然后我們來(lái)看一個(gè)示例程序:

package main
import (
"io"
"io/ioutil"
"log"
"os"
)
var (
Trace *log.Logger // 記錄所有日志
Info *log.Logger // 重要的信息
Warning *log.Logger // 警告信息
Error *log.Logger // 錯(cuò)誤信息
)
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")
}

運(yùn)行結(jié)果:

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)建并初始化一個(gè) 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ù)的第一個(gè)參數(shù) out 指定了日志要寫(xiě)入的目的地,這個(gè)參數(shù)傳入的值必須實(shí)現(xiàn)了 io.Writer 接口
  • 第二個(gè)參數(shù) prefix 會(huì)在生成的每行日志的最開(kāi)始出現(xiàn)
  • 第三個(gè)參數(shù) flag 定義日志包含哪些屬性

在本程序中:

  • Trace 日志記錄器使用了 ioutil 包里的 Discard 變量作為寫(xiě)到的目的地,所有的 Writer 調(diào)用都不會(huì)有動(dòng)作,但是會(huì)成功返回。當(dāng)某個(gè)等級(jí)的日志不重要時(shí),使用 Discard 變量可以禁用這個(gè)等級(jí)的日志。
  • 日志記錄器 Info 和 Warning 都使用 stdout 作為日志輸出。
  • 日志記錄去 Error 中的 New 函數(shù)第一個(gè)參數(shù)使用了 MultiWriter 函數(shù),這個(gè)函數(shù)調(diào)用會(huì)返回一個(gè) io.Writer 接口類型的值,這個(gè)值包含之前打開(kāi)的文件 file,以及 stderr。這個(gè)函數(shù)是一個(gè)變參函數(shù),可以接受任意個(gè)實(shí)現(xiàn)了 io.Writer 接口的值,所以會(huì)把所有傳入的 io.Writer 綁定在一起,當(dāng)對(duì)這個(gè)返回值進(jìn)行寫(xiě)入時(shí),會(huì)向所有綁在一起的 io.Writer 值做寫(xiě)入。從而實(shí)現(xiàn)向多個(gè) Writer 做輸出。這樣做的好處就是使用 Error 記錄器記錄日志時(shí),輸出會(huì)同時(shí)寫(xiě)到文件和 stderr 中。

總結(jié)

Golang 中 ??log?? 包的實(shí)現(xiàn)是基于對(duì)記錄日志這個(gè)需求長(zhǎng)時(shí)間的實(shí)踐和積累而形成的。比如將輸出寫(xiě)入 ??stdout??,將日志記錄到 ??stderr??,這同樣也是很多基于命令行界面的程序使用的方法。

寫(xiě)日志的第一件事就是找到一個(gè)完美的庫(kù)。然后,在您選擇了日志庫(kù)之后,您還需要計(jì)劃在代碼中的何處調(diào)用記錄器,如何存儲(chǔ)日志,如何在任何給定時(shí)間使它們可用,以及如何分析它們。

Go 日志的最佳實(shí)踐是從主應(yīng)用程序進(jìn)程中調(diào)用自定義記錄器,而不是在 goroutines 中。同時(shí)應(yīng)該將應(yīng)用程序中的日志消息寫(xiě)入本地文件,做到永久保存,同時(shí)針對(duì)錯(cuò)誤的信息應(yīng)該給到提醒,方便及時(shí)定位和處理。

到此這篇關(guān)于如何在 Go語(yǔ)言中使用日志包的文章就介紹到這了,更多相關(guān) Go使用日志包內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 從零封裝Gin框架實(shí)現(xiàn)數(shù)據(jù)庫(kù)初始化GORM

    從零封裝Gin框架實(shí)現(xiàn)數(shù)據(jù)庫(kù)初始化GORM

    這篇文章主要為大家介紹了從零封裝Gin框架實(shí)現(xiàn)數(shù)據(jù)庫(kù)初始化GORM,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2024-01-01
  • Golang生成Excel文檔的方法步驟

    Golang生成Excel文檔的方法步驟

    生成Excel是一個(gè)很常見(jiàn)的需求,本文將介紹如何使用Go的 Excelize庫(kù)去生成Excel文檔,以及一些具體場(chǎng)景下的代碼實(shí)現(xiàn),感興趣的可以參考一下
    2021-06-06
  • Golang之sync.Pool對(duì)象池對(duì)象重用機(jī)制總結(jié)

    Golang之sync.Pool對(duì)象池對(duì)象重用機(jī)制總結(jié)

    這篇文章主要對(duì)Golang的sync.Pool對(duì)象池對(duì)象重用機(jī)制做了一個(gè)總結(jié),文中有相關(guān)的代碼示例和圖解,具有一定的參考價(jià)值,需要的朋友可以參考下
    2023-07-07
  • 詳解Golang中Channel的原理和使用技巧

    詳解Golang中Channel的原理和使用技巧

    Channel管道提供了一種機(jī)制,它在兩個(gè)并發(fā)執(zhí)行的協(xié)程之間進(jìn)行同步,并通過(guò)傳遞與該管道元素類型相符的值來(lái)進(jìn)行通信。本文主要介紹了Channel的原理和使用技巧,需要的可以參考一下
    2022-11-11
  • 如何在Golang中運(yùn)行JavaScript

    如何在Golang中運(yùn)行JavaScript

    最近寫(xiě)一個(gè)程序,接口返回的數(shù)據(jù)是js格式的,需要通過(guò)golang來(lái)解析js,所以下面這篇文章主要給大家介紹了關(guān)于如何在Golang中運(yùn)行JavaScript的相關(guān)資料,需要的朋友可以參考下
    2022-01-01
  • 完美解決beego 根目錄不能訪問(wèn)靜態(tài)文件的問(wèn)題

    完美解決beego 根目錄不能訪問(wèn)靜態(tài)文件的問(wèn)題

    下面小編就為大家?guī)?lái)一篇完美解決beego 根目錄不能訪問(wèn)靜態(tài)文件的問(wèn)題。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2017-06-06
  • GoLang?Time時(shí)間操作函數(shù)講解

    GoLang?Time時(shí)間操作函數(shù)講解

    在日常開(kāi)發(fā)中,我們避免不了時(shí)間的使用,我們可能需要獲取當(dāng)前時(shí)間,然后格式化保存,也可能需要在時(shí)間類型與字符串類型之間相互轉(zhuǎn)換等。本文將會(huì)對(duì)?Go?time?包里面的常用函數(shù)和方法進(jìn)行介紹,需要的可以參考一下
    2023-01-01
  • 使用Go module和GoLand初始化一個(gè)Go項(xiàng)目的方法

    使用Go module和GoLand初始化一個(gè)Go項(xiàng)目的方法

    這篇文章主要介紹了使用Go module和GoLand初始化一個(gè)Go項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-12-12
  • Go語(yǔ)言atomic.Value如何不加鎖保證數(shù)據(jù)線程安全?

    Go語(yǔ)言atomic.Value如何不加鎖保證數(shù)據(jù)線程安全?

    這篇文章主要介紹了Go語(yǔ)言atomic.Value如何不加鎖保證數(shù)據(jù)線程安全詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-05-05
  • Goland 2020或2019軟件版本去掉a...或fmt...提示的方法

    Goland 2020或2019軟件版本去掉a...或fmt...提示的方法

    這篇文章主要介紹了Goland 2020或2019軟件版本去掉a...或fmt...提示的方法,本文通過(guò)圖文并茂的形式給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2020-10-10

最新評(píng)論