10篇文章带你手摸手封装gin框架(2)- Viper配置管理

5,869 阅读2分钟

前言

这是我参与更文挑战的第2天,大家好,我是作曲家种太阳
上一篇,我们学到了基本的目录设计和基本技术选型,也带大家做了一个gin的helloworld的程序
这篇会带你使用viper处理yaml配置文件并集成到gin框架中来~

1. 介绍

Viper是适用于Go应用程序的完整配置解决方案。它被设计用于在应用程序中工作,并且可以处理所有类型的配置需求和格式。它支持以下特性:

  1. • 设置默认值
  2. • 从JSON、TOML、YAML、HCL、envfile和Java properties格式的配置文件读取配置信息
  3. • 实时监控和重新读取配置文件(可选)
  4. • 从环境变量中读取
  5. • 从远程配置系统(etcd或Consul)读取并监控配置变化
  6. • 从命令行参数读取配置
  7. • 从buffer读取配置
  8. • 显式配置值

Viper官方地址

2. 安装

go get github.com/spf13/viper

2. 需求分析

思考下,一个服务需要哪些配置呢?

  1. 存放日志目录路径(logAddress)
  2. 服务名称(name)
  3. 服务端口号(port)
  4. mysql的端口号(port)和地址(host) ps:我们暂且先写这么多,后续还需要配置的我们慢慢加

3.数据流向图解

在写代码之前,我们得搞懂到settings-dev.yaml到viper识别,然后在到各个文件中,是怎么个过程 一张图,你就明白了~

image.png

3.编写settings-dev.yaml

# settings-dev.yaml
name: "go-gin"
port: 8022
logsAddress: "./logs/"

mysql:
 name: "root"
 host: "120.XX.XX.XX"
 port: 3306
 password: "XXXXXXXX"
 dbName: "test"
 
redis:
 host: "120.XX.XX.XX"
 port: 6379

4.定义配置的对应的struct

在config/config中编写几个结构体

viper会吧yaml的数据给对应的结构体

package config

type ServerConfig struct {
   Name        string      `mapstructure:"name"`
   Port        int         `mapstructure:"port"`
   Mysqlinfo   MysqlConfig `mapstructure:"mysql"`
   RedisInfo   RedisConfig `mapstructure:"redis"`
   LogsAddress string      `mapstructure:"logsAddress"`
}

type MysqlConfig struct {
   Host string `mapstructure:"host"`
   Port int    `mapstructure:"port"`
   Name string    `mapstructure:"name"`
   Password string    `mapstructure:"password"`
   DBName string    `mapstructure:"dbName"`
}

type RedisConfig struct {
   Host string `mapstructure:"host"`
   Port int    `mapstructure:"port"`
}

ps: 一定要注意 settings-dev.yaml每个字段名称和结构体的tag一一对应!!

5.编写global数据

global的数据主要是把viper的解析出来的数据存储,这样每个go文件都已引用glbal中的配置数据.
在 global/globalVar.go中编写

package global
import (
	"go.uber.org/zap"
	"go_gin/config"
)

var (
    Settings config.ServerConfig
)

6.使用Viper处理yaml配置

在 initialize/config中,编写

package initialize

import (
	"github.com/fatih/color"
	"github.com/spf13/viper"
	"go_gin/config"
	"go_gin/global"
)

func InitConfig() {
	// 实例化viper
	v := viper.New()
	//文件的路径如何设置
	v.SetConfigFile("./settings-dev.yaml")
	if err := v.ReadInConfig(); err != nil {
		panic(err)
	}
	serverConfig := config.ServerConfig{}
	//给serverConfig初始值
	if err := v.Unmarshal(&serverConfig); err != nil {
		panic(err)
	}
	// 传递给全局变量
	global.Settings = serverConfig
	color.Blue("11111111", global.Settings.LogsAddress)
}

7.使用配置变量

在 main.go中

package main

import (
   "fmt"
   "github.com/fatih/color"
   "go.uber.org/zap"
   "go_gin/global"
   "go_gin/initialize"   
   "go_gin/utils"
)

func main() {
   //1.初始化yaml配置
      initialize.InitConfig()

      r := gin.Default()
      r.GET("/ping", func(c *gin.Context) {
   	c.JSON(200, gin.H{
   		"message": "pong",
   	})
   })
   r.Run(fmt.Sprintf(":%d", global.Settings.Port))
}

最后-验证结果环节

启动 main.go 当你发现你在settings-dev.yaml配置端口号,在控制台打印,说明你就成功了~

image.png

思考

如何区分线上环境和开发环境的配置呢?