从本文开始,我们来看一下如何从零搭建一个 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