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