preface

The configuration file is an essential part of every project. It is used to save basic application data and database configuration information to avoid the embarrassment of searching for a configuration item to modify. Here I use Viper as a configuration management solution, it supports JSON, TOML, YAML, HCL, ENvFile, Java Properties and other formats of configuration files, and can monitor the modification of configuration files, hot overload, detailed introduction you can go to the official document to view

The installation

go get -u github.com/spf13/viper 
Copy the code

Writing configuration files

Create a new file in the project root directory, config.yaml, and put the basic configuration of the project first, we will add more configuration information later

app: Apply the basic configuration
  env: local # environment name
  port: 8888 Service monitor port number
  app_name: gin-app # app name
  app_url: http://localhost # Application domain name
Copy the code

Write configuration constructs

Create a folder config under the project root directory to store all configuration structures

Create the config.go file and define the Configuration structure, whose App property corresponds to App in config.yaml

package config

type Configuration struct {
    App App `mapstructure:"app" json:"app" yaml:"app"`
}
Copy the code

Create the app.go file and define the app structure, and all its attributes correspond to all configurations of app in config.yaml

package config

type App struct {
    Env string `mapstructure:"env" json:"env" yaml:"env"`
    Port string `mapstructure:"port" json:"port" yaml:"port"`
    AppName string `mapstructure:"app_name" json:"app_name" yaml:"app_name"`
    AppUrl string `mapstructure:"app_url" json:"app_url" yaml:"app_url"`
}
Copy the code

Note: The mapStructure tag in the configuration structure should correspond to the configuration name in config.ymal. Viper will assign config.yaml data to the structure based on the tag value

The global variable

Create a new global/app.go file and define the Application structure, which is used to store some variables at the start of the project, so that it is easy to call. At present, the Viper structure and the Configuration structure are put in first, and other member attributes will be added later

package global

import (
    "github.com/spf13/viper"
    "jassue-gin/config"
)

type Application struct {
    ConfigViper *viper.Viper
    Config config.Configuration
}

var App = new(Application)
Copy the code

Load the configuration using Viper

Create the bootstrap/config.go file and write the code:

package bootstrap

import (
    "fmt"
    "github.com/fsnotify/fsnotify"
    "github.com/spf13/viper"
    "jassue-gin/global"
    "os"
)

func InitializeConfig(a) *viper.Viper {
    // Set the configuration file path
    config := "config.yaml"
    // The production environment can change the configuration file path by setting environment variables
    if configEnv := os.Getenv("VIPER_CONFIG"); configEnv ! ="" {
        config = configEnv
    }

    // Initialize viper
    v := viper.New()
    v.SetConfigFile(config)
    v.SetConfigType("yaml")
    iferr := v.ReadInConfig(); err ! =nil {
        panic(fmt.Errorf("read config failed: %s \n", err))
    }

    // Listen for configuration files
    v.WatchConfig()
    v.OnConfigChange(func(in fsnotify.Event) {
        fmt.Println("config file changed:", in.Name)
        // Overload configuration
        iferr := v.Unmarshal(&global.App.Config); err ! =nil {
            fmt.Println(err)
        }
    })
    // Assign the configuration to the global variable
    iferr := v.Unmarshal(&global.App.Config); err ! =nil {
       fmt.Println(err)
    }

    return v
}
Copy the code

Initial Configuration

Modify the main.go file

package main

import (
    "github.com/gin-gonic/gin"
    "jassue-gin/bootstrap"
    "jassue-gin/global"
    "net/http"
)

func main(a) {
    // Initialize the configuration
    bootstrap.InitializeConfig()

    r := gin.Default()

    // Test the route
    r.GET("/ping".func(c *gin.Context) {
        c.String(http.StatusOK, "pong")})// Start the server
    r.Run(":" + global.App.Config.App.Port)
}
Copy the code

Run the go run main.go command to start the application. The port number that the server listens to is already specified in the configuration file