当前位置:网站首页>[go] Viper reads the configuration file in the go project

[go] Viper reads the configuration file in the go project

2022-06-12 05:33:00 cbdgz

introduction

Viper yes Go Complete configuration solution for applications , Include 12-Factor Applications . It is designed to work in applications , It can handle all types of configuration requirements and formats . It supports :

  • Set the default value
  • Read JSON、TOML、YAML、HCL、envfile and Java properties Properties profile
  • View and reread configuration files in real time ( Optional )
  • Read from environment variable
  • Configure the system remotely (etcd or Consor) Reading data , And observe the changes
  • Read... From the command line flag
  • Read from buffer
  • Set explicit values

Github Address :https://github.com/spf13/viper

Basic usage

  • Text to read toml Format configuration file as an example
  • The configuration file is defined as follows (config.toml)
[app]
port = 9000
init_models = false
loglevel = "debug"
logfile = "/tmp/app/log.log"
static_dir = "/tmp/app/static"
gateway = "localhost"

[secret]
jwt = "a-example-jwt-key"
package main

import (
	"fmt"
	"github.com/spf13/viper"
	"io/ioutil"
	"log"
	"os"
	"reflect"
	"strings"
)

// Configuration file structure , The contents of the configuration file need to be mapped one by one , More or less 
type Configure struct {
    
	App struct {
    
		InitModels bool   `json:"init_models" remark:" Whether to initialize the database model " must:"false"`
		Port       int64  `json:"port" remark:"http port "`
		Loglevel   string `json:"loglevel" remark:" The level of logging "`
		Logfile    string `json:"logfile" remark:" Log files "`
		StaticDir  string `json:"static_dir" remark:" Static file directory "`
		Gateway    string `json:"gateway" remark:" Gateway server " must:"false"`
	}

	Secret struct {
    
		JWT string `json:"jwt" remark:"jwt secret key "`
	}
}

//  initialization viper
func initViper() {
    
	viper.SetConfigName("config") // Specify the file name of the configuration file ( There is no need to specify the extension of the configuration file )
	viper.AddConfigPath(".")      //  Set configuration files and executable binaries in a directory 
	viper.AutomaticEnv()          // Automatically read matching parameters from environment variables 

	// Read -c Input path parameters , Initialize configuration file , Such as : ./main -c config.yaml
	if len(os.Args) >= 3 {
    
		if os.Args[1] == "-c" {
    
			cfgFile := os.Args[2]
			viper.SetConfigFile(cfgFile)
		}
	}

	//  Read and load the configuration file according to the above configuration 
	err := viper.ReadInConfig()
	if err != nil {
    
		log.Fatal(err)
	}

	// Use profile 
	file := viper.GetViper().ConfigFileUsed()
	configData, err := ioutil.ReadFile(file)
	if err != nil {
    
		log.Fatal(err)
	}
	// Get the configuration file text 
	configText := strings.ReplaceAll(string(configData), "&", "|||")
	// structure Reader
	r := strings.NewReader(configText)

	err = viper.ReadConfig(r)
	if err != nil {
    
		log.Fatalf(" Failed to initialize configuration file :%v", err)
	}
}

var Conf = &Configure{
    }

func main() {
    
	// initialization viper
	initViper()

	//reflect Reflection , Pass the configuration items in the configuration file through viper Import Conf in 
	confValue := reflect.ValueOf(Conf).Elem()
	confType := reflect.TypeOf(*Conf) // obtain Configure All in type

	for i := 0; i < confType.NumField(); i++ {
    
		section := confType.Field(i) // obtain Configure pass the civil examinations i individual type  for example i=0 Is for App
		sectionValue := confValue.Field(i)

		// Read section type information 
		for j := 0; j < section.Type.NumField(); j++ {
    
			key := section.Type.Field(j)
			keyValue := sectionValue.Field(j)

			// Get the lowercase name of the current partial configuration 
			sec := strings.ToLower(section.Name) // Configuration file section name 
			remark := key.Tag.Get("remark")      // Configuration notes 
			must := key.Tag.Get("must")          // Configuration notes 
			tag := key.Tag.Get("json")           // Configure key section name 
			if tag == "" {
    
				err := fmt.Errorf("can not found a tag name `json` in struct of [%s].%s", sec, tag)
				log.Fatal(err)
				os.Exit(-1)
			}

			// Bind environment variables , The values of environment variables will be used preferentially 
			log.Printf(" Bind environment variables  ENV_%s_%s ==> %s.%s", strings.ToUpper(sec), strings.ToUpper(tag), sec, tag)
			envKey := fmt.Sprintf("ENV_%s_%s", strings.ToUpper(sec), strings.ToUpper(tag))
			//  If the environment variable of the system is named envKey The environment variable of the system overwrites the value of the corresponding configuration item in the configuration with the value of the environment variable of the system 
			_ = viper.BindEnv(sec+"."+tag, envKey)
			fmt.Printf(" The environment variable obtained is :%v\n",os.Getenv(envKey))

			// Identify configuration fields by type 
			switch key.Type.Kind() {
    
			case reflect.String:
				value := viper.GetString(sec + "." + tag)
				if value == "" && must != "false" {
    
					err := fmt.Errorf("get a blank value of must item [%s].%s %s", sec, tag, remark)
					log.Fatal(err)
					os.Exit(-1)
				}
				keyValue.SetString(value)

			case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
				value := viper.GetInt64(sec + "." + tag)
				if value == 0 && must != "false" {
    
					err := fmt.Errorf("get a zero value of must item [%s].%s %s", sec, tag, remark)
					log.Fatal(err)
					os.Exit(-1)
				}
				keyValue.SetInt(value)

			case reflect.Bool:
				value := viper.GetBool(sec + "." + tag)
				keyValue.SetBool(value)

			case reflect.Slice:
				value := viper.GetStringSlice(sec + "." + tag)
				val := reflect.ValueOf(&value)
				keyValue.Set(val.Elem())

			default:
				log.Fatalf("unsupported config struct key type %T", key.Type.Kind())
			}
		}
	}
	log.Printf("The Result:%v\n",Conf)
}

原网站

版权声明
本文为[cbdgz]所创,转载请带上原文链接,感谢
https://yzsam.com/2022/03/202203010616199819.html