上一篇中已經講述了日誌庫的需求,這一篇中我們來實現日誌庫的原型。
新建一個專案,這裡我用的hm_log
,在專案下新建一個log_interface.go
日誌規範,定義日誌級別的方法:
package hm_log
type Log interface {
Debug(format string, args ...interface{}) // ...表示接收可變引數
Trace(format string, args ...interface{})
Info(format string, args ...interface{})
Warn(format string, args ...interface{})
Error(format string, args ...interface{})
Fatal(format string, args ...interface{})
Close() // 檔案需要進行關閉操作
}
複製程式碼
因為我們是要列印到檔案裡面去,所以我還需要新建一個file.go
:
package hm_log
type FileLog struct {
logPath string
logName string
}
func NewFileLog(logPath, logName string) Log {
// 為什麼返回的Log,上一篇中已經說明
return &FileLog{
logPath: logPath,
logName: logName,
}
}
func (f *FileLog) Debug(format string, args ...interface{}) {
}
func (f *FileLog) Trace(format string, args ...interface{}) {
}
func (f *FileLog) Info(format string, args ...interface{}) {
}
func (f *FileLog) Warn(format string, args ...interface{}) {
}
func (f *FileLog) Error(format string, args ...interface{}) {
}
func (f *FileLog) Fatal(format string, args ...interface{}) {
}
func (f *FileLog) Close() {
}
複製程式碼
現在我們基本實現了file的初始程式碼了,然後現在來實現file的功能。實現功能之前,新建一個log_const.go
,我們需要一些常量。
package hm_log
const (
DebugLevel = iota
TraceLevel
InfoLevel
WarnLevel
ErrorLevel
FatalLevel
)
複製程式碼
因為我們是寫入檔案中的,所以需要進行開啟檔案操作。為了在後續的日誌檢視方便,我們需要將普通日誌和錯誤日誌分開儲存。
type FileLog struct {
logPath string
logName string
file *os.File
warnFile *os.File
}
func NewFileLog(logPath, logName string) Log {
// 為什麼返回的Log,上一篇中已經說明
log := &FileLog{
logPath: logPath,
logName: logName,
}
log.init()
return log
}
func (f *FileLog) init() {
// 一般日誌
filename := fmt.Sprintf("%s/%s.log", f.logPath, f.logName)
file, err := os.OpenFile(filename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755) // os.O_CREATE 建立檔案 os.O_APPEND 追加寫入 os.O_WRONLY 只寫操作
if err != nil {
panic(fmt.Sprintf("open faile %s failed, err: %v", filename, err)
}
f.file = file
// 錯誤日誌
warnfilename := fmt.Sprintf("%s/%s.log.wf", f.logPath, f.logName)
warnfile, err := os.OpenFile(warnfilename, os.O_CREATE|os.O_APPEND|os.O_WRONLY, 0755) // os.O_CREATE 建立檔案 os.O_APPEND 追加寫入 os.O_WRONLY 只寫操作
if err != nil {
panic(fmt.Sprintf("open faile %s failed, err: %v", warnfilename, err)
}
f.warnFile = warnfile
}
複製程式碼
然後就可以實現之前的日誌方法了。
func (f *FileLog) Debug(format string, args ...interface{}) {
fmt.Fprintf(f.file, format, args...)
fmt.Fprintln(f.file)
}
func (f *FileLog) Trace(format string, args ...interface{}) {
fmt.Fprintf(f.file, format, args...)
fmt.Fprintln(f.file)
}
func (f *FileLog) Info(format string, args ...interface{}) {
fmt.Fprintf(f.file, format, args...)
fmt.Fprintln(f.file)
}
func (f *FileLog) Warn(format string, args ...interface{}) {
fmt.Fprintf(f.warnFile, format, args...)
fmt.Fprintln(f.warnFile)
}
func (f *FileLog) Error(format string, args ...interface{}) {
fmt.Fprintf(f.warnFile, format, args...)
fmt.Fprintln(f.warnFile)
}
func (f *FileLog) Fatal(format string, args ...interface{}) {
fmt.Fprintf(f.warnFile, format, args...)
fmt.Fprintln(f.warnFile)
}
func (f *FileLog) Close() {
f.file.Close()
f.warnFile.Close()
}
複製程式碼
到這裡檔案日誌庫基本完成了,當寫完一個功能時,我們需要進行單元測試,所以我們新建一個log_test.go
來測試我們寫的檔案日誌庫。
package log
import (
"testing"
)
func TestFileLog(t *testing.T) {
log := NewFileLog(".", "test")
log.Debug("this is file debub test")
log.Warn("this is file warn test")
log.Close()
}
複製程式碼
使用go test進行單元測試。然後可以看到我們的專案下多了一個test.log和test.log.wf檔案。開啟檔案,可以看到我們的日誌已經成功寫入了日誌檔案裡面。下一篇我們完善這個檔案日誌庫原型。