1 Introduction
Viperis a complete configuration solution for Go applications. It is designed to work within applications and can handle all types of configuration requirements and formats. Currently Star 26.6k, it supports the following features:
- Setting default values
- Reads configuration information from configuration files in JSON, TOML, YAML, HCL, envfile, and Java properties formats.
- Real-time monitoring and re-reading of configuration files (optional)
- Read from environment variable
- Read and monitor configuration changes from a remote configuration system (etcd or Consul)
- Reading Configuration from Command Line Parameters
- Read configuration from buffer
- explicit configuration value
2 Usage in Golang Projects
2.1 Installing Viper in go
# Enter the following command in the terminal
ArchitePlus@MacBook-Air % go get /spf13/viper
2.2 Preparation of a generic configuration file
Because it can support multiple configuration file formats, including JSON, TOML, YAML, HCL, INI, envfile and Java attribute files, it is convenient for developers to choose the appropriate format according to the needs of the project.
We'll use yaml as an example.
Create aconf
Folders, add subfoldersfiles
and then add the following, in which you can put some basic, generic configuration information.
app: # Basic application configuration
env: local # Environment name
port: 8888 # Service listening port number
app_name: traffic-demo # app name
app_url: http://localhost # Application access address
MySQL: # MySQL configuration
host: 127.0.0.1 # MySQL host address
port: 3306 # MySQL port number
user: root # MySQL username
password: <PASSWORD>
db_name: traffic # MySQL database name
As you can see, we have two pieces of configuration information, one for app and one for MySQL.
2.3 Writing user-defined configuration files
There are also some user-defined configuration files (there may be more than one), which need to be distinguished according to the different runtime environments (local, dev, beta, prod). Therefore, we will use theconfig/files/
Create four folders belowlocal
、dev
、beta
、prod
Four folders, each with afile, when
When the value of the file is changed, the file read is also changed, the following is the information of local
white_list.
user_id: # list of users
- 063105015
- 063105024
- 063105028
request_path: # Access path
- /api/v1/users
- /api/v1/ops
2.4 Structures for Configuration Mapping
We need a configuration structure (entity object) to map these two configurations, so that it's easy to call them later.
existconf
Add subfolders under the foldermodel
which holds the structure for parsing the mapping.and a
file, which reads as follows:
2.4.1
package config
// Configuration file parsing summary
type Configuration struct {
App App `mapstructure:"app" json:"app" yaml:"app"`
MYSQL MYSQL `mapstructure:"mysql" json:"mysql" yaml:"mysql"`
}
// Configuration file parsing:app
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"`
}
// Configuration file parsing:mysql
type MYSQL struct {
Host string `mapstructure:"host" json:"host" yaml:"host"`
Port string `mapstructure:"poet" json:"port" yaml:"port"`
User string `mapstructure:"user" json:"user" yaml:"user"`
Password string `mapstructure:"password" json:"password" yaml:"password"`
DbName string `mapstructure:"db_name" json:"db_name" yaml:"db_name"`
}
2.4.2
package config
type Custom struct {
WhiteList whiteList `mapstructure:"white_list" json:"white_list" yaml:"white_list"`
}
// Configuration file parsing summary
type whiteList struct {
UserId []string `mapstructure:"user_id" json:"user_id" yaml:"user_id"`
RequestPath []string `mapstructure:"request_path" json:"request_path" yaml:"request_path"`
}
2.5 Creating Global Global Variables Explained
Create a newglobal/
file, defines the Application structure, which is used to store some variables at the start of the project, so that they can be easily called.
For now, we'll put the viper structure and the Configuration structure in, and we'll add the rest of the configuration information later.
package global
import (
"/spf13/viper"
config "/config/model"
)
// Define a globalApplication
type Application struct {
ConfigViper *
Config
Custom
}
// initializationApplication
var App = new(Application)
2.5 Key Steps: Structure Mapping Logic
The configuration file has to be mapped to a structure so that the configuration data can be extracted, this side creates thebootstrap/
file, which serves as a carrier for the core parsing code, is as follows (the explanation in the code is clear enough):
package bootstrap
import (
"fmt"
"/fsnotify/fsnotify"
"/spf13/viper"
"/global"
)
// configAssemble is a generic function that assembles the configuration file and returns the pointer
//
// Parameters:
//
// configPath string - The path of the configuration file.
// viperStruct T - the structure to receive the configuration file.
//
// Return value:
//
// * - pointer
func configAssemble[T any](configPath string, viperStruct T) * {
// Initialize viper
v := ()
// Configuration file address
(configPath)
// Configuration file type, yaml
("yaml")
if err := (); err ! = nil {
panic(("read config failed: %s \n", err))
}
// Listen to the config file
()
(func(in ) {
("config file changed:", )
// Reload the configuration &
if err := (viperStruct); err ! = nil {
(err)
}
})
// Assign the configuration to the global variable &
if err := (viperStruct); err ! = nil {
(err)
}
return v
}
// InitializeConfig initializes the configuration function
func InitializeConfig() {
// Global application file configuration path, this is the address of our specific global config file
config := "conf/files/"
configAssemble(config, &)
// User-defined configuration (loads different config files for different environments)
customConfig := ("%s%s%s", "conf/files/", , "/")
configAssemble(customConfig, &)
}
2.6 The overall document structure is as follows
2.7 Operational results
The code is as follows:
package main
import (
"fmt"
"/global"
)
// main Functions are entry points to programs
func main() {
()
("Traffic Service Started...!")
var globalCong =
("globalCong: %+v\n", globalCong)
var customCong =
("customCong: %+v\n", customCong)
}
The effect is as follows:
3 Summary
Viper is a powerful, concise, and easy-to-use Go configuration library that helps developers easily manage application configuration and provides flexible access to the