Go中l(wèi)og包異或組合配置妙用詳解
log 中的這種用法,你一定見(jiàn)過(guò):
log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
沒(méi)見(jiàn)過(guò)的,自我反省下(逃
在 Go 語(yǔ)言的 log 包中,使用“位運(yùn)算相或” (|) 來(lái)配置日志的 flag,是為了讓我們靈活地組合多種日志信息輸出選項(xiàng)。,比如是否顯示日期、時(shí)間、微秒、文件名、行號(hào)等。
接下來(lái)詳細(xì)解釋這種方法的好處和原理。
1. 什么是 log 包中的 flag
在 log 包中,flag 是用來(lái)控制日志輸出格式的一些選項(xiàng)。
每種 flag 都是一個(gè)二進(jìn)制位掩碼,通過(guò)不同的掩碼組合,可以控制日志的顯示內(nèi)容。
這些 flag 選項(xiàng)定義如下:
const (
Ldate = 1 << iota // 日期:2009/01/23
Ltime // 時(shí)間:01:23:23
Lmicroseconds // 微秒級(jí)時(shí)間:01:23:23.123123(需要同時(shí)有 Ltime)
Llongfile // 完整文件名和行號(hào):/a/b/c/d.go:23
Lshortfile // 文件名和行號(hào):d.go:23(會(huì)覆蓋 Llongfile)
LUTC // 使用 UTC 時(shí)間而非本地時(shí)間
Lmsgprefix // 將“前綴”從行首移動(dòng)到消息之前
LstdFlags = Ldate | Ltime // 默認(rèn)值
)
這些常量是通過(guò)位移運(yùn)算 1 << iota 定義的,保證每個(gè) flag 只占用一位,且是唯一的。
這樣一來(lái),我們可以用按位或操作 | 來(lái)組合多個(gè)選項(xiàng)。
對(duì)應(yīng)的值如下:
const ( Ldate=1 << iota// iota =0,值為 1 << 0 = 1,二進(jìn)制:00000001,相當(dāng)于2的0次方 Ltime // iota = 1,值為 1 << 1 = 2,二進(jìn)制:00000010,相當(dāng)于2的1次方 Lmicroseconds // iota = 2,值為 1 << 2 = 4,二進(jìn)制:00000100,相當(dāng)于2的2次方 Llongfile // iota = 3,值為 1 << 3 = 8,二進(jìn)制:00001000,相當(dāng)于2的3次方 Lshortfile // iota = 4,值為 1 << 4 = 16,二進(jìn)制:00010000,相當(dāng)于2的4次方 LUTC // iota = 5,值為 1 << 5 = 32,二進(jìn)制:00100000,相當(dāng)于2的5次方 Lmsgprefix // iota = 6,值為 1 << 6 = 64,二進(jìn)制:01000000,相當(dāng)于2的6次方 )
2. 為什么使用按位或 (|) 來(lái)組合 flag
按位或 (|) 的好處是可以任意組合選項(xiàng)。因?yàn)槊總€(gè) flag 常量代表一個(gè)獨(dú)特的二進(jìn)制位,所以它們可以通過(guò)按位或相加組合在一起,而不會(huì)產(chǎn)生沖突。例如:
Ltime的值是1 << 1,即0b0010Llongfile的值是1 << 3,即0b1000
當(dāng)我們使用 log.SetFlags(Ltime | Llongfile) 時(shí),相當(dāng)于將 0b0010 | 0b1000 組合成 0b1010,即同時(shí)啟用了時(shí)間和文件名短格式顯示。
通過(guò)這種位運(yùn)算方式,可以組合各種 flag 選項(xiàng),而不必為每種組合重新定義一個(gè)新的常量。
3. 使用按位或組合 flag 的優(yōu)勢(shì)
- 靈活性高:可以自由選擇多個(gè)選項(xiàng)的組合,滿足不同需求,而不必逐一指定每個(gè)
flag。 - 可讀性強(qiáng):按位或組合表達(dá)式簡(jiǎn)單明了,清楚地顯示啟用了哪些功能。
- 高效性:位運(yùn)算本身效率高,計(jì)算量小,而且
flag常量設(shè)計(jì)成二進(jìn)制掩碼,便于快速組合和解讀。
4. 如何識(shí)別已設(shè)置的flag
當(dāng)我們通過(guò)位或組合多個(gè)flag傳遞給log.SetFlags后,log包在輸出日志時(shí)會(huì)檢測(cè)該組合值,并根據(jù)不同的位設(shè)置來(lái)確定輸出內(nèi)容。
具體的識(shí)別方式:按位與(&)操作
假設(shè)我們?cè)O(shè)置了以下flag組合:
log.SetFlags(log.Ldate | log.Ltime | log.Llongfile)
傳入的flag組合會(huì)是一個(gè)整型值,log包會(huì)在生成日志時(shí),通過(guò)按位與操作來(lái)判斷每個(gè)flag是否存在。具體步驟如下:
- 檢查
Ldate:使用按位與操作flags & Ldate,如果結(jié)果不為0,則表示Ldate已被設(shè)置,那么日志將包含日期信息。 - 檢查
Ltime:同樣,通過(guò)flags & Ltime,非零表示Ltime被設(shè)置,日志中將包含時(shí)間信息。 - 檢查
Llongfile:按位檢查flags & Llongfile,通過(guò)判斷值來(lái)確定是否輸出文件路徑(完整路徑)。
具體來(lái)看,假設(shè)我們使用log.Ldate | log.Ltime | log.Llongfile:
Ldate的值為00000001。Ltime的值為00000010。Llongfile的值為00001000。
將這些flag組合在一起后的整型值是00001011,它包含了所有的設(shè)置信息。
示例:代碼實(shí)現(xiàn)flag識(shí)別的過(guò)程
以log包的實(shí)現(xiàn)原理為例,可以大致模擬flag識(shí)別的過(guò)程。假設(shè)flags變量存儲(chǔ)了當(dāng)前的flag設(shè)置值,可以如下判斷是否開(kāi)啟各個(gè)功能:
package main
import (
"log"
)
func main() {
flags := log.Ldate | log.Ltime | log.Llongfile
if flags&log.Ldate != 0 {
log.Print("日期已啟用")
}
if flags&log.Ltime != 0 {
log.Print("時(shí)間已啟用")
}
if flags&log.Llongfile != 0 {
log.Print("完整文件路徑已啟用")
}
}
5. 使用展示
我們來(lái)看一個(gè)例子,假設(shè)這段代碼位于 main.go 文件的第 10 行:
package main
import (
"log"
)
func main() {
log.SetFlags(log.Ltime | log.Lshortfile)
log.Println("這是一個(gè)日志消息")
}
如果這段代碼在 2024 年 11 月 3 日 15:04:05 執(zhí)行,日志輸出可能會(huì)是:
15:04:05 main.go:10: 這是一個(gè)日志消息
其中,15:04:05 是時(shí)間,main.go:10 是簡(jiǎn)化的文件名和行號(hào)。
6. 總結(jié)
使用按位或操作符 | 來(lái)配置日志 flag,可以讓我們靈活地組合日志的不同顯示選項(xiàng),方便地自定義輸出格式。這種方式不僅簡(jiǎn)化了代碼,還提高了日志配置的靈活性和可讀性。
到此這篇關(guān)于Go中l(wèi)og包異或組合配置妙用詳解的文章就介紹到這了,更多相關(guān)Go log包異或組合內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- golang 日志log與logrus示例詳解
- go語(yǔ)言中的log 包示例詳解
- Golang日志庫(kù)logrus的介紹與使用示例代碼
- Go log庫(kù)的使用示例詳解
- Go標(biāo)準(zhǔn)庫(kù)Flag庫(kù)和Log庫(kù)的使用
- 源碼分析Golang?log是如何實(shí)現(xiàn)的
- Go?1.21.0?新增結(jié)構(gòu)化日志記錄標(biāo)準(zhǔn)庫(kù)log/slog使用詳解
- golang結(jié)構(gòu)化日志log/slog包之slog.Record的用法簡(jiǎn)介
- go中l(wèi)og包的實(shí)現(xiàn)示例
相關(guān)文章
Go依賴注入DI工具wire使用詳解(golang常用庫(kù)包)
依賴注入是指程序運(yùn)行過(guò)程中,如果需要調(diào)用另一個(gè)對(duì)象協(xié)助時(shí),無(wú)須在代碼中創(chuàng)建被調(diào)用者,而是依賴于外部的注入,本文結(jié)合示例代碼給大家介紹Go依賴注入DI工具wire使用,感興趣的朋友一起看看吧2022-04-04
golang監(jiān)聽(tīng)文件變化的實(shí)例
這篇文章主要介紹了golang監(jiān)聽(tīng)文件變化的實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2021-03-03
Golang實(shí)現(xiàn)驗(yàn)證一個(gè)字符串是否為URL
在實(shí)際開(kāi)發(fā)過(guò)程中,有時(shí)候會(huì)遇到?URL?的校驗(yàn)問(wèn)題,Go?語(yǔ)言中有哪些方法去驗(yàn)證一個(gè)字符串是否滿足?URL?格式呢?本文就來(lái)和大家詳細(xì)講講2023-04-04
Golang中Broadcast 和Signal區(qū)別小結(jié)
本文解析Go中sync.Cond的Signal與Broadcast區(qū)別,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2025-06-06
Go語(yǔ)言基礎(chǔ)入門(mén)應(yīng)用簡(jiǎn)介及常用命令
這篇文章主要為大家介紹了Go語(yǔ)言基礎(chǔ)入門(mén)應(yīng)用簡(jiǎn)介及常用命令,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2021-11-11
如何使用Goland IDE go mod 方式構(gòu)建項(xiàng)目
這篇文章主要介紹了如何使用Goland IDE go mod 方式構(gòu)建項(xiàng)目,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2020-10-10

