从0开始的Go开发之旅 web篇-(2)配置文件

上一篇博客我们介绍了项目布局, 这一篇介绍关于配置文件

目录

  1. 项目布局
  2. 配置文件

这次我们选用yaml来作为配置文件的格式

在项目的config目录下, 新建一个config.yaml文件

Server:
  RunMode: debug
  HttpPort: 8000
  ReadTimeout: 60
  WriteTimeout: 60

App:
  LogSavePath: ./logs/
  LogFileName: app
  LogFileExt: .log
  TokenExpire: 12
  Secert: asdfghjjkuytttrrr
  FedidTokenHeaderKey: xxxx
  FedidTokenHeaderType: xx
  FedidTokenUrl: xxxx
  FedidUserInfoUrl: xxx

Database:
  Username: xx
  Password: x.
  Host: x.x.x.x
  DBName: x
  Charset: utf8mb4
  ParseTime: True
  MaxIdleCoons: 10
  MaxOpenConns: 30

Server段

我们定义了一些关于gin的配置, 比如运行模式, 在开发中, 我们使用debug, 在生产环境时, 使用release, 其他比如监听端口, 超时时间等

App段

我们定义了一些应用相关的配置, 比如日志保存的路径, 名字, 后缀, 以及token的秘钥, 过期时间, Fedid相关的配置是我们公司有统一认证的api, 所以我们这边只需要调用那边的api , 获取用户信息, 然后在我们的数据库中创建用户, 进行权限认证

Database段

定义了数据库相关的配置, 账号,密码,主机名, 库名, 字符集, 空闲连接数, 最大连接数等


接着我们写关于解析配置文件的代码, 在config文件夹在新建一个setting文件夹, 再新建两个文件

section.go

package setting

import "time"

type ServerSettingS struct {
	RunMode      string
	HttpPort     string
	ReadTimeout  time.Duration
	WriteTimeout time.Duration
}

type AppSettingS struct {
	LogSavePath          string
	LogFileName          string
	LogFileExt           string
	Secert               string
	TokenExpire          time.Duration
	CallBackUrl          string
	FedidTokenHeaderKey  string
	FedidTokenHeaderType string
	FedidTokenUrl        string
	FedidUserInfoUrl     string
	SecertByte           []byte
}

type DatabaseSettingS struct {
	UserName     string
	Password     string
	Host         string
	DBName       string
	Charset      string
	ParseTime    bool
	MaxIdleConns int
	MaxOpenConns int
}

func (s *Setting) ReadSection(k string, v interface{}) error {
	err := s.vp.UnmarshalKey(k, v)
	if err != nil {
		return err
	}

	return nil
}

setting.go

package setting

import "github.com/spf13/viper"

type Setting struct {
	vp *viper.Viper
}

func NewSetting() (*Setting, error) {
	vp := viper.New()
	vp.SetConfigName("config")
	vp.AddConfigPath("config/")
	vp.SetConfigType("yaml")
	err := vp.ReadInConfig()
	if err != nil {
		return nil, err
	}
	return &Setting{vp}, nil
}

我们选择了viper作为解析配置文件的库

在setting的go中, 定义了NewSetting方法, 里面读取了配置文件, 返回了Setting结构体的实例

在section.go中, 我们定义了3个结构体, 分别对应配置文件的三段, 它们的属性分别对应了配置文件中的单项配置. ReadSection方法把viper读取到的值返回给对应的结构体


接着我们在global文件夹下, 新建setting.go文件

package global

import (
	"gin_study/config/setting"
)

var (
	ServerSetting   *setting.ServerSettingS
	AppSetting      *setting.AppSettingS
	DatabaseSetting *setting.DatabaseSettingS
)

修改一下main.go的内容

package main

import (
	"fmt"
	"gin_study/config/setting"
	"gin_study/global"
	"log"
	"time"

	"github.com/gin-gonic/gin"
)

func setupSetting() error {
	setting, err := setting.NewSetting()
	if err != nil {
		return err
	}
	err = setting.ReadSection("Server", &global.ServerSetting)
	if err != nil {
		return err
	}
	err = setting.ReadSection("App", &global.AppSetting)
	if err != nil {
		return err
	}
	err = setting.ReadSection("Database", &global.DatabaseSetting)
	if err != nil {
		return err
	}

	global.ServerSetting.ReadTimeout *= time.Second
	global.ServerSetting.WriteTimeout *= time.Second
	global.AppSetting.TokenExpire *= time.Hour
	global.AppSetting.SecertByte = []byte(global.AppSetting.Secert)
	return nil
}

func init() {
	err := setupSetting()
	if err != nil {
		log.Fatalf("初始化配置文件异常: %v", err)
	}

}

func main() {
	fmt.Println(global.ServerSetting.RunMode)
	gin.SetMode(global.ServerSetting.RunMode)
	r := gin.Default()
	r.GET("/ping", func(ctx *gin.Context) {
		ctx.JSON(200, gin.H{"message": "pong"})
	})
	r.Run()
}

定义了一个setupSetting函数, 分别读取不同的section, 赋值给global中对应的结构体, 然后在init函数中, 读取配置, 这样我们在其他所有包, 就可以直接调用global.xxSetting.xx去获取配置文件中的值, 非常方便

可以看到我们运行时, 可以打印出global.ServerSetting.RunMode为正确的值

下一篇介绍关于数据库的配置


评论

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注