Go Web实战之创建项目及增加日志功能

 更新时间:2022年11月10日 09:42:45   作者:宇宙之一粟  
这篇文章主要为大家详细介绍了Go Web项目中如何实现创建项目及增加日志功能,文中的示例代码讲解详细,感兴趣的小伙伴可以了解一下

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

就像之前第一次写一个 HelloWorld 项目一样,run 命令会成功编译并执行我们的 Println() 内的字符串 Let's Go,输出结果如下:

$ go run .
Let's Go

创建一些基本的项目功能

众所周知,Web 应用有一些基础的服务和功能如日志、文件配置等等。所以我们可以为 sports 项目提供一些基本的服务,这些服务将为运行网络应用程序提供基础。

创建日志接口 Logger

先来实现第一个服务器功能——日志。Go 标准库中的 log 包为创建日志提供了一套非常用户友好的基本功能,但在实际开发过程中,仍需要一些额外的功能来筛选一些信息详情。

创建 sports/logging 文件夹,然后在这个文件夹下面创建一个 logging.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{})
}

上面的代码定义了 Logger 接口,并具体声明了具体的日志消息的具体方法,分别有着不同的日志级别,LogLevel 从 Trace 到 Fatal 。值得注意的是也有一个无级别的 None, 意味着没有日志输出。

对于每个级别的重要性,Logger 接口定义两个方法:

  • 一个用于接受简单字符串的方法,如 Debug
  • 一个用于接收模板字符串和占位符值的方法,如 Debugf

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

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() 函数创建一个具有最小严重程度日志 DefaultLogger 和 log.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)
}

由 NewDefaultLogger 创建的最小日志级别被设置为 Information,这意味着更低的日志级别(Trace 和 Debug)将被忽略,再次编译和执行 sports 项目,就会看到本地的日志输出,可能你按照我的操作只会时间戳不同,如下:

$ go run .
11:46:55 INFO Let's Go, logger

终端结果如图所示:

总结

到了本文的总结时刻了,为了学习 Go Web 项目,本文先回顾了一下 Go 项目的初始化构建和运行过程,然后往我们的 sports 项目中添加了一个日志功能,逐步完善日志接口和实现,最后在主函数中进行了一个简单的日志输出测试。

到此这篇关于Go Web实战之创建项目及增加日志功能的文章就介绍到这了,更多相关Go Web增加日志内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • 一文带你了解Go语言中的匿名函数

    一文带你了解Go语言中的匿名函数

    无论是在Go语言还是其他编程语言中,匿名函数都扮演着重要的角色,本文将详细介绍Go语言中匿名函数的概念和使用方法,感兴趣的小伙伴可以跟随小编一起学习一下
    2023-06-06
  • Go排序算法通用qsort函数使用示例

    Go排序算法通用qsort函数使用示例

    这篇文章主要为大家介绍了Go排序算法通用qsort函数使用示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-11-11
  • 一文带你轻松理解Go中的内存逃逸问题

    一文带你轻松理解Go中的内存逃逸问题

    这篇文章主要给大家介绍Go中的内存逃逸问题,文中通过代码示例讲解的非常详细,对我们的学习或工作有一定的参考价值,感兴趣的同学可以跟着小编一起来学习
    2023-06-06
  • 浅析Go语言中Channel的各种用法

    浅析Go语言中Channel的各种用法

    这篇文章主要带大家一起来学习一下Go语言中的if语句,也就是大家口中的判断语句。文中的示例代码讲解详细,对我们学习Go语言有一定帮助,需要的可以参考一下
    2022-11-11
  • Go CSV包实现结构体和csv内容互转工具详解

    Go CSV包实现结构体和csv内容互转工具详解

    这篇文章主要介绍了Go CSV包实现结构体和csv内容互转工具详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-03-03
  • go语言单例模式(Singleton)实例分析

    go语言单例模式(Singleton)实例分析

    这篇文章主要介绍了go语言单例模式(Singleton),实例分析了单例模式的原理与Go语言的实现技巧,需要的朋友可以参考下
    2015-03-03
  • Go 语言 JSON 标准库的使用

    Go 语言 JSON 标准库的使用

    今天通过本文给大家介绍Go 语言 JSON 标准库的使用小结,包括序列化和反序列化的相关知识,感兴趣的朋友跟随小编一起看看吧
    2021-10-10
  • Golang使用Consul详解

    Golang使用Consul详解

    Consul是一个服务发现软件, 提供了服务发现\键值存储\健康检查等功能,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2022-06-06
  • 解决golang 反射interface{}做零值判断的一个重大坑

    解决golang 反射interface{}做零值判断的一个重大坑

    这篇文章主要介绍了解决golang 反射interface{}做零值判断的一个重大坑,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧
    2021-04-04
  • golang使用viper加载配置文件实现自动反序列化到结构

    golang使用viper加载配置文件实现自动反序列化到结构

    这篇文章主要为大家介绍了golang使用viper加载配置文件实现自动反序列化到结构示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2023-08-08

最新评论