日志處理和正則處理
- 1、logx日志處理
- 1.1、logx簡介
- 1.2、日志初始化與配置
- 1.3、常用方法
- 1.4、配合defer捕獲panic
- 2、正則處理
- 2.1、正則表達式語法大全
- 2.2、基本匹配
- 2.3、常見函數使用
- 2.4、從html提取漢字demo
1、logx日志處理
1.1、logx簡介
logx
是 go-zero
框架中用于日志記錄的核心包,具有以下特點:
- 統一日志格式(帶時間、級別、調用棧)
- 自動日志切割
- 支持多種日志輸出模式(控制臺、文件、volume)
- 支持鏈路追蹤(context 支持)
- 支持日志等級控制(debug/info/error/alert)
- 內建 panic 捕獲機制,防止程序崩潰
type LogConf struct {ServiceName string `json:",optional"`Mode string `json:",default=console,options=[console,file,volume]"`Encoding string `json:",default=json,options=[json,plain]"`TimeFormat string `json:",optional"`Path string `json:",default=logs"`Level string `json:",default=info,options=[info,error,severe]"`Compress bool `json:",optional"`KeepDays int `json:",optional"`StackCooldownMillis int `json:",default=100"`MaxBackups int `json:",default=0"`MaxSize int `json:",default=0"`Rotation string `json:",default=daily,options=[daily,size]"`
}
ServiceName
:設置服務名稱,可選。在volume
模式下,該名稱用于生成日志文件。在rest/zrpc
服務中,名稱將被自動設置為rest
或zrpc
的名稱。Mode
:輸出日志的模式,默認是console
console
模式將日志寫到stdout/stderr
file
模式將日志寫到Path
指定目錄的文件中volume
模式在docker
中使用,將日志寫入掛載的卷中Encoding
: 指示如何對日志進行編碼,默認是json
json
模式以json
格式寫日志plain
模式用純文本寫日志,并帶有終端顏色顯示TimeFormat
:自定義時間格式,可選。默認是2006-01-02T15:04:05.000Z07:00
Path
:設置日志路徑,默認為logs
Level
: 用于過濾日志的日志級別。默認為info
info
,所有日志都被寫入error, info
的日志被丟棄severe
,info
和error
日志被丟棄,只有severe
日志被寫入
Compress
: 是否壓縮日志文件,只在file
模式下工作KeepDays
:日志文件被保留多少天,在給定的天數之后,過期的文件將被自動刪除。對console
模式沒有影響tackCooldownMillis
:多少毫秒后再次寫入堆棧跟蹤。用來避免堆棧跟蹤日志過多MaxBackups
: 多少個日志文件備份將被保存。0代表所有備份都被保存。當Rotation
被設置為size時才會起作用。注意:KeepDays
選項的優先級會比MaxBackups
高,即使MaxBackups
被設置為0,當達到KeepDays
上限時備份文件同樣會被刪除。MaxSize
: 當前被寫入的日志文件最大可占用多少空間。0代表沒有上限。單位為MB。當Rotation
被設置為size
時才會起作用。Rotation
: 日志輪轉策略類型。默認為daily(按天輪轉)。daily
按天輪轉。size
按日志大小輪轉。
方法介紹:
Error, Info, Slow
: 將任何類型的信息寫進日志,使用fmt.Sprint(...)
來轉換為string
Errorf, Infof, Slowf
: 將指定格式的信息寫入日志Errorv, Infov, Slowv
: 將任何類型的信息寫入日志,用json marshal
編碼Errorw, Infow, Sloww
: 寫日志,并帶上給定的key:value
字段WithContext
:將給定的 ctx 注入日志信息,例如用于記錄trace-id
和span-id
WithDuration
: 將指定的時間寫入日志信息中,字段名為duration
logx快速使用示例:
package mainimport "github.com/zeromicro/go-zero/core/logx"func main() {logx.Info("服務啟動...")logx.Errorf("出現錯誤: %v", "連接失敗")
}
注意:如果不現實設置,默認采用console模式,輸出到控制臺。
1.2、日志初始化與配置
package mainimport "github.com/zeromicro/go-zero/core/logx"func main() {logx.MustSetup(logx.LogConf{ServiceName: "user-api",Mode: "file",Path: "./logs",Level: "info",KeepDays: 7,Encoding: "plain",})defer logx.Close()logx.Info("服務初始化完成")
}
1.3、常用方法
package mainimport "github.com/zeromicro/go-zero/core/logx"func main() {logx.Info("服務器初始化完成...")logx.Infof("%s", "服務器初始化完成...")logx.Debug(1, 2, 3, []int{1, 2, 3}, "hello world")logx.Debugf("測試%s-%d", "DEBUG", 1)logx.Error("錯誤日志-1", "錯誤日志-2")logx.Errorf("%s-%d", "錯誤日志", 3)logx.Alert("嚴重警告日志...")
}
1.4、配合defer捕獲panic
package mainimport "github.com/zeromicro/go-zero/core/logx"func test() {defer func() {if err := recover(); err != nil {logx.Error(err)}}()panic("出錯...")
}func main() {test()
}
2、正則處理
Golang中通過regexp包支持正則表達式操作,使用前需要導入該包。
import "regexp"
2.1、正則表達式語法大全
2.2、基本匹配
使用regexp.MatchString()函數來判斷是否含有對應的字符串或數組。
其中第一個參數是正則表達式,第二參數表示要匹配的字符串。
簡單匹配字符串:
package mainimport ("fmt""regexp"
)func main() {str := "hello,world"ok, _ := regexp.MatchString("hello", str)if ok {fmt.Println("字符串中包含hello")} else {fmt.Println("字符串中不包含hello")}
}
匹配字符串中是否包含數字:
package mainimport ("fmt""regexp"
)func main() {str := "cost: ¥20"ok, _ := regexp.MatchString("[0-9]+", str)if ok {fmt.Println("字符串中包含數字...")} else {fmt.Println("字符串中不包含數字...")}
}
2.3、常見函數使用
一般還會配合 regexp.MustCompile
來使用,傳入一個正則表達式,返回一個 *MustCompile
對象。調用該函數要保證正則表達式是正確的,否則直接引發panic。
1、FindAllString
:查找所有匹配數字返回
package mainimport ("fmt""regexp"
)func main() {str := "今日消費內容: ¥20, ¥10, ¥15, ¥5, ¥55"re := regexp.MustCompile(`\d+`)slice := re.FindAllString(str, -1)fmt.Println(slice)
}
第二個參數表示匹配的數量n,如果傳入<0的數表示沒有數量限制。
2、FindString
:查找第一個匹配的子串
package mainimport ("fmt""regexp"
)func main() {str := "123 abc 456"re := regexp.MustCompile(`\d+`)res := re.FindString(str)fmt.Println(res) // 123
}
3、FindStringSubmatch
:返回匹配的子串和分組
package mainimport ("fmt""regexp"
)func main() {str := "日期: 2025-06-06"re := regexp.MustCompile(`(\d{4})-(\d{2})-(\d{2})`)slice := re.FindStringSubmatch(str)for k, v := range slice {fmt.Printf("slice[%d]: %v\n", k, v)}
}
4、SubexpNames
:命名并編號的捕獲分組
package mainimport ("fmt""regexp"
)func main() {str := "今日日期: 2025-06-06"re := regexp.MustCompile(`(?P<year>\d{4})-(?P<month>\d{2})-(?P<day>\d{2})`)res := re.FindStringSubmatch(str)names := re.SubexpNames()for i, name := range names {if i > 0 {fmt.Printf("%s: %s\n", name, res[i])}}}
注意:由于FindStringSubmatch返回的是匹配串和對應分組,所以下標應該從1開始。
5、ReplaceAllString
:字符串替換
package mainimport ("fmt""regexp"
)func main() {str := "今日消費: ¥20, ¥30, ¥10, ¥5, ¥15"re := regexp.MustCompile(`\d+`)res := re.ReplaceAllString(str, "**")fmt.Println(res)
}
6、Split
:按正則分割字符串
package mainimport ("fmt""regexp"
)func main() {re := regexp.MustCompile(`[,\s;]+`)parts := re.Split("a, b; c d", -1)fmt.Println(parts) // [a b c d]
}
2.4、從html提取漢字demo
package mainimport ("fmt""io""os""regexp"
)func main() {file, err := os.Open("index.html")defer file.Close()if err != nil {fmt.Println(err)return}var str []bytevar tmp = make([]byte, 128)for {n, err := file.Read(tmp)if err == io.EOF {break}if err != nil {fmt.Println(err)}str = append(str, tmp[:n]...)}re := regexp.MustCompile(`[\p{Han}]+`)slice := re.FindAllString(string(str), -1)var res stringfor _, v := range slice {res += v}fmt.Println("提取出的中文內容:", res)
}