详解Go语言中配置文件使用与日志配置


Posted in Golang onJune 01, 2022

只是简单的把GET和POST接口的使用测试了一下。

我还是想按照正常的项目结构调整一下,这篇笔记主要是三个部分:调整项目目录结构、增加配置文件使用、增加日志配置,很常规而且也是每个项目都需要用到的。

项目地址:github地址 

项目结构调整

说先对项目目录结构调整一下,按照我自己的开发习惯,增加了几个目录。

项目结构如下图:

详解Go语言中配置文件使用与日志配置

解释一下目录结构

  • app/constants:主要放置一些常量
  • app/controllers:控制层,熟悉java的不多说。
  • app/errors:异常定义目录
  • app/pojo:结构体定义文件,主要是接口请求的结构体和接口返回的结构体,或者自定义的结构体。
  • app/router:路由文件
  • app/services:服务实现逻辑目录
  • app/utils:工具文件目录
  • config/log:日志配置文件目录,后面会讲到怎么使用。
  • config/toml:配置文件使用,后面会讲到怎么使用。
  • main.go作为程序的主入口。

配置文件使用

在我们项目结构中,经常会使用到配置文件。配置文件里面会记录像mysql用户名、端口、redis配置信息等等内容。下面先配置一下toml_config.go,来对config.toml配置文件读取。

详解Go语言中配置文件使用与日志配置

下面是toml_config.go的内容

package toml
 
import (
    "fmt"
    "github.com/spf13/viper"
)
 
type TomlConfig struct {
    AppName string
    Log     LogConfig
}
 
// 日志保存地址
type LogConfig struct {
    Path  string
    Level string
}
 
var c TomlConfig
 
func init() {
    // 设置文件名
    viper.SetConfigName("config")
    // 设置文件类型
    viper.SetConfigType("toml")
    // 设置文件路径,可以多个viper会根据设置顺序依次查找
    viper.AddConfigPath(".")
    viper.AutomaticEnv()
    err := viper.ReadInConfig()
    if err != nil {
        panic(fmt.Errorf("fatal error config file: %s", err))
    }
 
    viper.Unmarshal(&c)
}
func GetConfig() TomlConfig {
    return c
}

需要安装几个库,命令如下:

go get github.com/natefinch/lumberjack
go get go.uber.org/zap/zapcore

注意,在go文件中,init方法在加载该文件所在包的时候会默认执行。

我们看一下配置的内容,主要是日志级别和存放地址。

验证的话,等下面日志配置好了一起看一下。

详解Go语言中配置文件使用与日志配置

日志配置

下面继续配置一下日志,也可以看到配置文件里面配置的日志级别和存放地址都是日志的配置项。

主要在config/log下的logger.go文件,配置了日志相关内容。

详解Go语言中配置文件使用与日志配置

logger.go的内容如下

package log
 
import (
    "os"
 
    "github.com/natefinch/lumberjack"
    "go.uber.org/zap"
    "go.uber.org/zap/zapcore"
)
 
type Field = zap.Field
 
var (
    Logger  *zap.Logger
    String  = zap.String
    Any     = zap.Any
    Int     = zap.Int
    Float32 = zap.Float32
)
 
// logpath 日志文件路径
// loglevel 日志级别
func InitLogger(logpath string, loglevel string) {
    // 日志分割
    hook := lumberjack.Logger{
        Filename:   logpath, // 日志文件路径,默认 os.TempDir()
        MaxSize:    100,     // 每个日志文件保存100M,默认 100M
        MaxBackups: 30,      // 保留30个备份,默认不限
        MaxAge:     7,       // 保留7天,默认不限
 
        Compress: true, // 是否压缩,默认不压缩
    }
    write := zapcore.AddSync(&hook)
    // 设置日志级别
    // debug 可以打印出 info debug warn
    // info  级别可以打印 warn info
    // warn  只能打印 warn
    // debug->info->warn->error
    var level zapcore.Level
    switch loglevel {
    case "debug":
        level = zap.DebugLevel
    case "info":
        level = zap.InfoLevel
    case "error":
        level = zap.ErrorLevel
    case "warn":
        level = zap.WarnLevel
    default:
        level = zap.InfoLevel
    }
    encoderConfig := zapcore.EncoderConfig{
        TimeKey:        "time",
        LevelKey:       "level",
        NameKey:        "logger",
        CallerKey:      "linenum",
        MessageKey:     "msg",
        StacktraceKey:  "stacktrace",
        LineEnding:     zapcore.DefaultLineEnding,
        EncodeLevel:    zapcore.LowercaseLevelEncoder,  // 小写编码器
        EncodeTime:     zapcore.ISO8601TimeEncoder,     // ISO8601 UTC 时间格式
        EncodeDuration: zapcore.SecondsDurationEncoder, //
        EncodeCaller:   zapcore.FullCallerEncoder,      // 全路径编码器
        EncodeName:     zapcore.FullNameEncoder,
    }
    // 设置日志级别
    atomicLevel := zap.NewAtomicLevel()
    atomicLevel.SetLevel(level)
 
    var writes = []zapcore.WriteSyncer{write}
    // 如果是开发环境,同时在控制台上也输出
    if level == zap.DebugLevel {
        writes = append(writes, zapcore.AddSync(os.Stdout))
    }
    core := zapcore.NewCore(
        zapcore.NewConsoleEncoder(encoderConfig),
        // zapcore.NewJSONEncoder(encoderConfig),
        zapcore.NewMultiWriteSyncer(writes...), // 打印到控制台和文件
        // write,
        level,
    )
    // 开启开发模式,堆栈跟踪
    caller := zap.AddCaller()
    // 开启文件及行号
    development := zap.Development()
    // 设置初始化字段,如:添加一个服务器名称
    filed := zap.Fields(zap.String("application", "test-gin"))
    // 构造日志
    Logger = zap.New(core, caller, development, filed)
    Logger.Info("Logger init success")
}

需要安装依赖包,命令如下

go get github.com/spf13/viper

在main.go文件增加logger的初始化加载,看看配置文件和日志是否都生效了。

main.go增加下面的代码

详解Go语言中配置文件使用与日志配置

看一下执行的日志

2022-05-31T21:27:54.964+0800    info   D:/goProject/learn-gin/config/log/logger.go:90 Logger init success    {"application": "test-gin"}
2022-05-31T21:27:54.964+0800   info   D:/goProject/learn-gin/main.go:31  hahahah    {"application": "test-gin"}
2022-05-31T21:27:54.964+0800   info   D:/goProject/learn-gin/main.go:32  config {"application": "test-gin", "config": {"AppName":"learn-gin","Log":{"Path":"logs/learn.log","Level":"debug"}}}

可以看到配置文件内容的打印,还有日志的打印效果,OK,舒服了。

小结

这有几个点要注意下:

1、init()和main()方法是golang默认的两个方法,不需要我们调用,程序执行会自动寻找项目中的这俩方法。如果引入了一个包,会优先执行引入包的init方法,再执行自己包内的init方法。

2、如果go项目构建是报错:missing go.sum entry for module providing package xxxxx

执行一下命令:

go build -mod=mod

到此这篇关于详解Go语言中配置文件使用与日志配置的文章就介绍到这了,更多相关Go语言日志配置内容请搜索三水点靠木以前的文章或继续浏览下面的相关文章希望大家以后多多支持三水点靠木!


Tags in this post...

Golang 相关文章推荐
golang interface判断为空nil的实现代码
Apr 24 Golang
Go缓冲channel和非缓冲channel的区别说明
Apr 25 Golang
golang 实现菜单树的生成方式
Apr 28 Golang
解决golang 关于全局变量的坑
May 06 Golang
Golang二维数组的使用方式
May 28 Golang
Go语言空白表示符_的实例用法
Jul 04 Golang
K8s部署发布Golang应用程序的实现方法
Jul 16 Golang
Golang解析JSON对象
Apr 30 Golang
Golang实现可重入锁的示例代码
May 25 Golang
GoFrame基于性能测试得知grpool使用场景
Jun 21 Golang
Go语言编译原理之变量捕获
Aug 05 Golang
GO中sync包自由控制并发示例详解
Aug 05 Golang
详解Go语言中Get/Post请求测试
Golang实现可重入锁的示例代码
May 25 #Golang
Go web入门Go pongo2模板引擎
May 20 #Golang
Go语言入门exec的基本使用
May 20 #Golang
Golang并发工具Singleflight
May 06 #Golang
深入理解 Golang 的字符串
May 04 #Golang
Golang入门之计时器
May 04 #Golang
You might like
PHP 木马攻击防御技巧
2009/06/13 PHP
如何批量清理系统临时文件(语言:C#、 C/C++、 php 、python 、java )
2016/02/01 PHP
yii2的restful api路由实例详解
2019/05/14 PHP
js function使用心得
2010/05/10 Javascript
javascript动画之圆形运动,环绕鼠标运动作小球
2010/07/20 Javascript
jquery 全局AJAX事件使用代码
2010/11/05 Javascript
鼠标移入移出事件改变图片的分辨率的两种方法
2013/12/17 Javascript
jQuery实现带玻璃流光质感的手风琴特效
2015/11/20 Javascript
jquery取消事件冒泡的三种方法(推荐)
2016/05/28 Javascript
原生js代码实现图片放大境效果
2016/10/30 Javascript
基于JavaScript实现拖动滑块效果
2017/02/16 Javascript
jquery实现图片平滑滚动详解
2017/03/22 jQuery
VUE axios上传图片到七牛的实例代码
2017/07/28 Javascript
vue-router项目实战总结篇
2018/02/11 Javascript
vue 输入电话号码自动按3-4-4分割功能的实现代码
2020/04/30 Javascript
基于原生JS封装的Modal对话框插件的示例代码
2020/09/09 Javascript
python正则表达式re模块详细介绍
2014/05/29 Python
python实现requests发送/上传多个文件的示例
2018/06/04 Python
总结Python图形用户界面和游戏开发知识点
2019/05/22 Python
Python3批量生成带logo的二维码方法
2019/06/24 Python
Python OpenCV调用摄像头检测人脸并截图
2020/08/20 Python
python机器学习实现决策树
2019/11/11 Python
python 字典套字典或列表的示例
2019/12/16 Python
python怎么判断模块安装完成
2020/06/19 Python
Python requests模块安装及使用教程图解
2020/06/30 Python
详解python中的闭包
2020/09/07 Python
解决Python 写文件报错TypeError的问题
2020/10/23 Python
自荐信的禁忌和要点
2013/10/15 职场文书
自考自我鉴定范文
2013/10/30 职场文书
2014年驾驶员工作总结
2014/11/18 职场文书
实习工作表现评语
2014/12/31 职场文书
灵山大佛导游词
2015/02/04 职场文书
酒店收银员岗位职责
2015/04/07 职场文书
家长对学校的意见和建议
2015/06/03 职场文书
党校培训学习心得体会
2016/01/06 职场文书
Java常用工具类汇总 附示例代码
2021/06/26 Java/Android