真实的国产乱ⅩXXX66竹夫人,五月香六月婷婷激情综合,亚洲日本VA一区二区三区,亚洲精品一区二区三区麻豆

成都創(chuàng)新互聯(lián)網(wǎng)站制作重慶分公司

go語言代碼log輸出,go log庫

Golang將日志同時(shí)輸出到控制臺和文件

日常開發(fā)當(dāng)中需要將golang的log包打印的日志同時(shí)輸出到控制臺和文件,應(yīng)該如何解決這個(gè)問題?

創(chuàng)新互聯(lián)長期為千余家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對不同對象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺,與合作伙伴共同營造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為屯溪企業(yè)提供專業(yè)的成都網(wǎng)站建設(shè)、成都網(wǎng)站制作,屯溪網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。

log包可以通過SetOutput()方法指定日志輸出的方式(Writer),但是只能指定一個(gè)輸出的方式(Writer)。我們利用io.MultiWriter()將多個(gè)Writer拼成一個(gè)Writer使用的特性,把log.Println()輸出的內(nèi)容分流到控制臺和文件當(dāng)中。

原文地址

golang logger輸出格式怎么修改

1.Logger結(jié)構(gòu)

首先來看下類型Logger的定義:

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

buf []byte // for accumulating text to write

}

主要有5個(gè)成員,其中3個(gè)我們比較熟悉,分別是表示Log前綴的 "prefix",表示Log頭標(biāo)簽的 "flag" ,以及Log的輸出目的地out。 buf是一個(gè)字節(jié)數(shù)組,主要用來存放即將刷入out的內(nèi)容,相當(dāng)于一個(gè)臨時(shí)緩存,在對輸出內(nèi)容進(jìn)行序列化時(shí)作為存儲目的地。 mu是一個(gè)mutex主要用來作線程安全的實(shí)習(xí),當(dāng)有多個(gè)goroutine同時(shí)往一個(gè)目的刷內(nèi)容的時(shí)候,通過mutex保證每次寫入是一條完整的信息。

2.std及整體結(jié)構(gòu)

在前一篇文章中我們提到了log模塊提供了一套包級別的簡單接口,使用該接口可以直接將日志內(nèi)容打印到標(biāo)準(zhǔn)錯(cuò)誤。那么該過程是怎么實(shí)現(xiàn)的呢?其實(shí)就是通過一個(gè)內(nèi)置的Logger類型的變量 "std" 來實(shí)現(xiàn)的。該變量使用:

var std = New(os.Stderr, "", LstdFlags)

進(jìn)行初始化,默認(rèn)輸出到系統(tǒng)的標(biāo)準(zhǔn)輸出 "os.Stderr" ,前綴為空,使用日期加時(shí)間作為Log抬頭。

當(dāng)我們調(diào)用 log.Print的時(shí)候是怎么執(zhí)行的呢?我們看其代碼:

func Print(v ...interface{}) {

std.Output(2, fmt.Sprint(v...))

}

這里實(shí)際就是調(diào)用了Logger對象的 Output方法,將日志內(nèi)容按照fmt包中約定的格式轉(zhuǎn)義后傳給Output。Output定義如下 :

func (l *Logger) Output(calldepth int, s string) error

其中s為日志沒有加前綴和Log抬頭的具體內(nèi)容,xxxxx 。該函數(shù)執(zhí)行具體的將日志刷入到對應(yīng)的位置。

3.核心函數(shù)的實(shí)現(xiàn)

Logger.Output是執(zhí)行具體的將日志刷入到對應(yīng)位置的方法。

該方法首先根據(jù)需要獲得當(dāng)前時(shí)間和調(diào)用該方法的文件及行號信息。然后調(diào)用formatHeader方法將Log的前綴和Log抬頭先格式化好 放入Logger.buf中,然后再將Log的內(nèi)容存入到Logger.buf中,最后調(diào)用Logger.out.Write方法將完整的日志寫入到輸出目的地中。

由于寫入文件以及拼接buf的過程是線程非安全的,因此使用mutex保證每次寫入的原子性。

l.mu.Lock()

defer l.mu.Unlock()

將buf的拼接和文件的寫入放入這個(gè)后面,使得在多個(gè)goroutine使用同一個(gè)Logger對象是,不會(huì)弄亂buf,也不會(huì)雜糅的寫入。

該方法的第一個(gè)參數(shù)最終會(huì)傳遞給runtime.Caller的skip,指的是跳過的棧的深度。這里我記住給2就可以了。這樣就會(huì)得到我們調(diào)用log 是所處的位置。

在golang的注釋中說鎖住 runtime.Caller的過程比較重,這點(diǎn)我還是不很了解,只是從代碼中看到其在這里把鎖打開了。

if l.flag(Lshortfile|Llongfile) != 0 {

// release lock while getting caller info - it‘s expensive.

l.mu.Unlock()

var ok bool

_, file, line, ok = runtime.Caller(calldepth)

if !ok {

file = "???"

line = 0

}

l.mu.Lock()

}

在formatHeader里面首先將前綴直接復(fù)制到Logger.buf中,然后根據(jù)flag選擇Log抬頭的內(nèi)容,這里用到了一個(gè)log模塊實(shí)現(xiàn)的 itoa的方法,作用類似c的itoa,將一個(gè)整數(shù)轉(zhuǎn)換成一個(gè)字符串。只是其轉(zhuǎn)換后將結(jié)果直接追加到了buf的尾部。

縱觀整個(gè)實(shí)現(xiàn),最值得學(xué)習(xí)的就是線程安全的部分。在什么位置合適做怎樣的同步操作。

4.對外接口的實(shí)現(xiàn)

在了解了核心格式化和輸出結(jié)構(gòu)后,在看其封裝就非常簡單了,幾乎都是首先用Output進(jìn)行日志的記錄,然后在必要的時(shí)候 做os.exit或者panic的操作,這里看下Fatal的實(shí)現(xiàn)。

func (l *Logger) Fatal(v ...interface{}) {

l.Output(2, fmt.Sprint(v...))

os.Exit(1)

}

// Fatalf is equivalent to l.Printf() followed by a call to os.Exit(1).

func (l *Logger) Fatalf(format string, v ...interface{}) {

l.Output(2, fmt.Sprintf(format, v...))

os.Exit(1)

}

// Fatalln is equivalent to l.Println() followed by a call to os.Exit(1).

func (l *Logger) Fatalln(v ...interface{}) {

l.Output(2, fmt.Sprintln(v...))

os.Exit(1)

}

這里也驗(yàn)證了我們之前做的Panic的結(jié)果,先做輸出日志操作。再進(jìn)行panic。

Go語言基礎(chǔ)語法(一)

本文介紹一些Go語言的基礎(chǔ)語法。

先來看一個(gè)簡單的go語言代碼:

go語言的注釋方法:

代碼執(zhí)行結(jié)果:

下面來進(jìn)一步介紹go的基礎(chǔ)語法。

go語言中格式化輸出可以使用 fmt 和 log 這兩個(gè)標(biāo)準(zhǔn)庫,

常用方法:

示例代碼:

執(zhí)行結(jié)果:

更多格式化方法可以訪問中的fmt包。

log包實(shí)現(xiàn)了簡單的日志服務(wù),也提供了一些格式化輸出的方法。

執(zhí)行結(jié)果:

下面來介紹一下go的數(shù)據(jù)類型

下表列出了go語言的數(shù)據(jù)類型:

int、float、bool、string、數(shù)組和struct屬于值類型,這些類型的變量直接指向存在內(nèi)存中的值;slice、map、chan、pointer等是引用類型,存儲的是一個(gè)地址,這個(gè)地址存儲最終的值。

常量是在程序編譯時(shí)就確定下來的值,程序運(yùn)行時(shí)無法改變。

執(zhí)行結(jié)果:

執(zhí)行結(jié)果:

Go 語言的運(yùn)算符主要包括算術(shù)運(yùn)算符、關(guān)系運(yùn)算符、邏輯運(yùn)算符、位運(yùn)算符、賦值運(yùn)算符以及指針相關(guān)運(yùn)算符。

算術(shù)運(yùn)算符:

關(guān)系運(yùn)算符:

邏輯運(yùn)算符:

位運(yùn)算符:

賦值運(yùn)算符:

指針相關(guān)運(yùn)算符:

下面介紹一下go語言中的if語句和switch語句。另外還有一種控制語句叫select語句,通常與通道聯(lián)用,這里不做介紹。

if語法格式如下:

if ... else :

else if:

示例代碼:

語法格式:

另外,添加 fallthrough 會(huì)強(qiáng)制執(zhí)行后面的 case 語句,不管下一條case語句是否為true。

示例代碼:

執(zhí)行結(jié)果:

下面介紹幾種循環(huán)語句:

執(zhí)行結(jié)果:

執(zhí)行結(jié)果:

也可以通過標(biāo)記退出循環(huán):

--THE END--

Go語言之log(如何將日志寫到指定文件里面)

對于Go語言的日志來說,如何將log寫到指定的文件里面,下面是一個(gè)例子。

output:

output:

golang怎么將控制臺的錯(cuò)誤輸出寫入文件

你可以記錄下錯(cuò)誤,然后寫入文件?;蛘咴趩?dòng)go程序的時(shí)候,把輸出寫入文件。

像這樣: ./main a.log


本文名稱:go語言代碼log輸出,go log庫
分享地址:http://weahome.cn/article/hcgdee.html

其他資訊

在線咨詢

微信咨詢

電話咨詢

028-86922220(工作日)

18980820575(7×24)

提交需求

返回頂部