从本文开始,我们来看一下如何从零搭建一个 Go 项目。

回顾一下基础的 Go 项目运行过程

sports
go mod init sports

main.go
package main

import "fmt"

func writeMessage() {
  fmt.Println("Let's Go")
}

func main() {
  writeMessage()
}

回到终端,编译并执行我们的项目:

go run .
HelloWorldrunPrintln()
$ go run .
Let's Go

创建一些基本的项目功能

sports

创建日志接口 Logger

log
sports/logginglogging.go
package logging

type LogLevel int

const (
    Trace LogLevel = iota
    Debug
    Information
    Warning
    Fatal
    None
)

type Logger interface {
    Trace(string)
    Tracef(string, ...interface{})

    Debug(string)
    Debugf(string, ...interface{})

    Info(string)
    Infof(string, ...interface{})

    Warn(string)
    Warnf(string, ...interface{})

    Panic(string)
    Panicf(string, ...interface{})
}
LoggerLogLevelTraceFatalNone
Logger
DebugDebugf

将日志功能定义为接口的好处是:在需要更改或替换功能时,只需要更改实现,我们的调用接口并不需要改变;接口也使得功能作为服务提供给应用程序。

Logger 接口的具体实现

Logger
logger_default.go
package logging

import (
    "fmt"
    "log"
)

type DefaultLogger struct {
    minLevel     LogLevel
    loggers      map[LogLevel]*log.Logger
    triggerPanic bool
}

func (l *DefaultLogger) MinLogLevel() LogLevel {
    return l.minLevel
}

func (l *DefaultLogger) write(level LogLevel, message string) {
    if l.minLevel <= level {
        l.loggers[level].Output(2, message)
    }
}

func (l *DefaultLogger) Trace(msg string) {
    l.write(Trace, msg)
}

func (l *DefaultLogger) Tracef(template string, vals ...interface{}) {
    l.write(Trace, fmt.Sprintf(template, vals...))
}

func (l *DefaultLogger) Debug(msg string) {
    l.write(Debug, msg)
}

func (l *DefaultLogger) Debugf(template string, vals ...interface{}) {
    l.write(Debug, fmt.Sprintf(template, vals...))
}

func (l *DefaultLogger) Info(msg string) {
    l.write(Information, msg)
}

func (l *DefaultLogger) Infof(template string, vals ...interface{}) {
    l.write(Information, fmt.Sprintf(template, vals...))
}

func (l *DefaultLogger) Warn(msg string) {
    l.write(Warning, msg)
}

func (l *DefaultLogger) Warnf(template string, vals ...interface{}) {
    l.write(Warning, fmt.Sprintf(template, vals...))
}

func (l *DefaultLogger) Panic(msg string) {
    l.write(Fatal, msg)
    if l.triggerPanic {
        panic(msg)
    }
}

func (l *DefaultLogger) Panicf(template string, vals ...interface{}) {
    formattedMsg := fmt.Sprintf(template, vals...)
    l.write(Fatal, formattedMsg)
    if l.triggerPanic {
        panic(formattedMsg)
    }
}
NewDefaultLogger()DefaultLoggerlog.Loggers

最终我们的目录结构如下:

测试日志功能

main()main.go
package main

import (
    // "fmt"
    "sports/logging"
)

func writeMessage(logger logging.Logger) {
    // fmt.Println("Let's Go")
    logger.Info("Let's Go, logger")
}

func main() {

    var logger logging.Logger = logging.NewDefaultLogger(logging.Information)
    writeMessage(logger)
}
NewDefaultLoggerInformationTraceDebugsports
$ go run .
11:46:55 INFO Let's Go, logger

终端结果如图所示:

总结

sports
您可能感兴趣的文章: