📝 Go config manage(load,get,set). support JSON, YAML, TOML, INI, HCL, ENV and Flags. Multi file load, data override merge, parse ENV var. Go应用配置加载管理,支持多种格式,多文件加载,远程文件加载,支持数据合并,解析环境变量名

Config

GitHub go.mod Go version Codacy Badge GoDoc Build Status Actions Status Coverage Status Go Report Card

Golang's application config manage tool library.

中文说明

Features

  • Support multi format: JSON(default), INI, YAML, TOML, HCL, ENV, Flags
    • JSON content support comments. will auto clear comments
    • Other drivers are used on demand, not used will not be loaded into the application.
      • Possibility to add custom driver for your specific format
  • Support multi-file and multi-data loading
  • Support loading configuration from os ENV
  • Support for loading configuration data from remote URLs
  • Support for setting configuration data from command line arguments(flags)
  • Support data overlay and merge, automatically load by key when loading multiple copies of data
  • Support for binding all or part of the configuration data to the structure
  • Support get sub value by path, like map.key arr.2
  • Support parse ENV name and allow with default value. like envKey: ${SHELL|/bin/bash} -> envKey: /bin/zsh
  • Generic api Get Int Uint Int64 Float String Bool Ints IntMap Strings StringMap ...
  • Complete unit test(code coverage > 95%)

Provide a sub-package dotenv that supports importing data from files (eg .env) to ENV

Only use INI

If you just want to use INI for simple config management, recommended use gookit/ini

GoDoc

Usage

Here using the yaml format as an example(testdata/yml_other.yml):

name: app2
debug: false
baseKey: value2
shell: ${SHELL}
envKey1: ${NotExist|defValue}

map1:
    key: val2
    key2: val20

arr1:
    - val1
    - val21

Load data

examples code please see _examples/yaml.go:

package main

import (
    "github.com/gookit/config/v2"
    "github.com/gookit/config/v2/yaml"
)

// go run ./examples/yaml.go
func main() {
	config.WithOptions(config.ParseEnv)
	
	// add driver for support yaml content
	config.AddDriver(yaml.Driver)
	// config.SetDecoder(config.Yaml, yaml.Decoder)

	err := config.LoadFiles("testdata/yml_base.yml")
	if err != nil {
		panic(err)
	}

	// load more files
	err = config.LoadFiles("testdata/yml_other.yml")
	// can also load multi at once
	// err := config.LoadFiles("testdata/yml_base.yml", "testdata/yml_other.yml")
	if err != nil {
		panic(err)
	}
	
	// fmt.Printf("config data: \n %#v\n", config.Data())
}

Map Data To Structure

Note: The default binding mapping tag of a structure is mapstructure, which can be changed by setting Options.TagName

user := struct {
    Age  int
    Kye  string
    UserName  string `mapstructure:"user_name"`
    Tags []int
}{}
err = config.BindStruct("user", &user)

fmt.Println(user.UserName) // inhere

Direct Read data

  • Get integer
age := config.Int("age")
fmt.Print(age) // 100
  • Get bool
val := config.Bool("debug")
fmt.Print(val) // true
  • Get string
name := config.String("name")
fmt.Print(name) // inhere
  • Get strings(slice)
arr1 := config.Strings("arr1")
fmt.Printf("%#v", arr1) // []string{"val1", "val21"}
  • Get string map
val := config.StringMap("map1")
fmt.Printf("%#v",val) // map[string]string{"key":"val2", "key2":"val20"}
  • Value contains ENV var
value := config.String("shell")
fmt.Print(value) // "/bin/zsh"
  • Get value by key path
// from array
value := config.String("arr1.0")
fmt.Print(value) // "val1"

// from map
value := config.String("map1.key")
fmt.Print(value) // "val2"
  • Setting new value
// set value
config.Set("name", "new name")
name = config.String("name")
fmt.Print(name) // "new name"

Load from flags

Support simple flags parameter parsing, loading

// flags like: --name inhere --env dev --age 99 --debug

// load flag info
keys := []string{"name", "env", "age:int" "debug:bool"}
err := config.LoadFlags(keys)

// read
config.String("name") // "inhere"
config.String("env") // "dev"
config.Int("age") // 99
config.Bool("debug") // true

Load from ENV

// os env: APP_NAME=config APP_DEBUG=true
// load ENV info
config.LoadOSEnv([]string{"APP_NAME", "APP_DEBUG"}, true)

// read
config.Bool("app_debug") // true
config.String("app_name") // "config"

New Config Instance

You can create custom config instance

// create new instance, will auto register JSON driver
myConf := config.New("my-conf")

// create empty instance
myConf := config.NewEmpty("my-conf")

// create and with some options
myConf := config.NewWithOptions("my-conf", config.ParseEnv, config.ReadOnly)

Available Options

// Options config options
type Options struct {
	// parse env value. like: "${EnvName}" "${EnvName|default}"
	ParseEnv bool
	// config is readonly. default is False
	Readonly bool
	// enable config data cache. default is False
	EnableCache bool
	// parse key, allow find value by key path. default is True eg: 'key.sub' will find `map[key]sub`
	ParseKey bool
	// tag name for binding data to struct
	TagName string
	// the delimiter char for split key, when `FindByPath=true`. default is '.'
	Delimiter byte
	// default write format. default is JSON
	DumpFormat string
	// default input format. default is JSON
	ReadFormat string
}

API Methods Refer

Load Config

  • LoadOSEnv(keys []string) Load from os ENV
  • LoadData(dataSource ...interface{}) (err error) Load from struts or maps
  • LoadFlags(keys []string) (err error) Load from CLI flags
  • LoadExists(sourceFiles ...string) (err error)
  • LoadFiles(sourceFiles ...string) (err error)
  • LoadRemote(format, url string) (err error)
  • LoadSources(format string, src []byte, more ...[]byte) (err error)
  • LoadStrings(format string, str string, more ...string) (err error)

Getting Values

  • Bool(key string, defVal ...bool) bool
  • Int(key string, defVal ...int) int
  • Uint(key string, defVal ...uint) uint
  • Int64(key string, defVal ...int64) int64
  • Ints(key string) (arr []int)
  • IntMap(key string) (mp map[string]int)
  • Float(key string, defVal ...float64) float64
  • String(key string, defVal ...string) string
  • Strings(key string) (arr []string)
  • StringMap(key string) (mp map[string]string)
  • Get(key string, findByPath ...bool) (value interface{})

Setting Values

  • Set(key string, val interface{}, setByPath ...bool) (err error)

Useful Methods

  • Getenv(name string, defVal ...string) (val string)
  • AddDriver(driver Driver)
  • Data() map[string]interface{}
  • SetData(data map[string]interface{}) set data to override the Config.Data
  • Exists(key string, findByPath ...bool) bool
  • DumpTo(out io.Writer, format string) (n int64, err error)
  • BindStruct(key string, dst interface{}) error

Run Tests

go test -cover
// contains all sub-folder
go test -cover ./...

Gookit packages

  • gookit/ini Go config management, use INI files
  • gookit/rux Simple and fast request router for golang HTTP
  • gookit/gcli build CLI application, tool library, running CLI commands
  • gookit/event Lightweight event manager and dispatcher implements by Go
  • gookit/cache Generic cache use and cache manager for golang. support File, Memory, Redis, Memcached.
  • gookit/config Go config management. support JSON, YAML, TOML, INI, HCL, ENV and Flags
  • gookit/color A command-line color library with true color support, universal API methods and Windows support
  • gookit/filter Provide filtering, sanitizing, and conversion of golang data
  • gookit/validate Use for data validation and filtering. support Map, Struct, Form data
  • gookit/goutil Some utils for the Go: string, array/slice, map, format, cli, env, filesystem, test and more
  • More please see https://github.com/gookit

See also

License

MIT

Owner
Gookit
Useful libs for the Go(router, DI, log, config, cache, event, validate, filter, CLI, i18n, respond-data, view-render)
Gookit
Comments
  • How to parse ini to struct if data within [brackets] is variable?

    How to parse ini to struct if data within [brackets] is variable?

    Hello, I was wondering how I might go about parsing to a struct a file like below:

    [variablename1]
    type = 
    client_id = 
    client_secret = 
    scope = 
    token = 
    
    

    [variablename1] will always be unique as it is a name assigned at the time of creation of the ini, the rest of the fields will always have the same key name.

    I was going to have:

    type Settings struct {
    	Remote struct {
    		Type         string `json:"type"`
    		ClientId     string `json:"client_id"`
    		ClientSecret string `json:"client_secret"`
    		Scope        int    `json:"scope"`
    		Token        int    `json:"token"`
    	} `json:"???"` // --- This will always be different
    }
    
    

    Is there a way to deal with this? Thanks, -MH

  • 文件名后缀作为判断依据的问题

    文件名后缀作为判断依据的问题

    对于一些工具的配置文件,格式虽然可能是ini,yaml或者json 但是为了区分这些文件的作用,可能不再是ini,yaml这样的后缀, 而是会以rules,system这样的后缀结尾, 而我看你的parseSourceCode()中会检查这样的后缀,作为文件格式的判断依据 但是对于上述描述到的文件,就会被认定为不合法的文件格式,

    对于这样的情况能否给个方法,可以让我直接指定文件格式,从而解决这样的问题呢?

  • mapstructure.DecoderConfig.Squash support config in Options()

    mapstructure.DecoderConfig.Squash support config in Options()

    cfgLoader := config.NewWithOptions("", func(options *config.Options) {
        options.TagName = "json"
        options.Squash  = true
    })
    
    type Test1 struct {
        B int `json:"b"`
    }
    type Test2 struct {
        Test1
        C int `json:"c"`
    }
    cfg := &Test2{}
    
    cfgLoader.BindStruct("", cfg)
    
    mapConf := &mapstructure.DecoderConfig{
    		Metadata: nil,
    		Result:   dst,
    		TagName:  c.opts.TagName,
                    Squash :  c.opts.Squash ,                   // support embedded structs
    		// will auto convert string to int/uint
    		WeaklyTypedInput: true,
    	}
    
    
  • Got panic when load json then yaml to overwrite a key in json

    Got panic when load json then yaml to overwrite a key in json

    config/test0.json:

    {
        "lang": {
            "allowed": {
                "en": "ddd"
            }
        }
    }
    

    config/test1.yaml:

    lang:
      allowed:
        en: "666"
    

    run the following code:

    package main
    
    import (
    	"fmt"
    	"os"
    	"path/filepath"
    
    	"github.com/gookit/config/v2"
    	"github.com/gookit/config/v2/yaml"
    )
    
    func main() {
    	config.AddDriver(yaml.Driver)
    	config.Default().Options().TagName = "json"
    
    	filepath.Walk("config", func(path string, info os.FileInfo, err error) error {
    		if err != nil {
    			return err
    		}
    
    		if info.IsDir() {
    			return nil
    		}
    
    		fmt.Printf("loading %s...\n", path)
    		return config.LoadFiles(path)
    	})
    }
    

    got this panic:

    loading config/test0.json...
    loading config/test1.yaml...
    panic: reflect.Value.MapIndex: value of type interface {} is not assignable to type string
    

    if reverse the loading order, i.e. load test1.yaml first then test0.json, it works

  • Support Pretty Print?

    Support Pretty Print?

    Would be nice to have support for pretty print out-of-the-box like Viper. Currently: config.Set()

    {"parent":{"child":{"grandChild":"Test Val"}}}
    

    Expecting:

    {
      "parent": {
        "child": {
          "grandChild": "Test Val"
        }
      }
    }
    

    Is this posible? Or any work-around for this?

  • [FEAT] Support Set with Slice (Array) Index Using Square Brackets?

    [FEAT] Support Set with Slice (Array) Index Using Square Brackets?

    It would be nice to support slice index in .Set() Example:

    config.Set("parent.child[0]", "Test1")
    config.Set("parent.child[1]", "Test2")
    

    CUrrently, the result will be like:

    {
        "parent": {
            "child[0]": "Test1",
            "child[1]": "Test1"
        }
    }
    

    ==> Expecting result would look like:

    {
        "parent": {
            "child": [
              "Test1",
              "Test2"
            ]
        }
    }
    

    Thanks,

  • ini: invalid data to encode as ini

    ini: invalid data to encode as ini

    解析ini文件时候,使用了ini.Driver 但在把data写会文件时候,发生了"ini: invalid data to encode as ini" 使用(* config)DumpTo() method 查看代码发现ini的Encode代码是这么写的:

    func Encode(v interface{}, defSection ...string) (out []byte, err error) {
        switch vd := v.(type) {
        case map[string]interface{}: // from full mode
            return EncodeFull(vd, defSection...)
        case map[string]map[string]string: // from simple mode
            return EncodeSimple(vd, defSection...)
        default:
            err = errors.New("ini: invalid data to encode as ini")
        }
        return
    }
    

    但是在func (c *Config) DumpTo(out io.Writer, format string) (n int64, err error)却是这么调用的

        // encode data to string
        encoded, err := encoder(&c.data)
        if err != nil {
            return
        }
    

    取的是c.data的地址(&c.data),所以type永远匹配不上 所以这里或许是个bug,还是说,这里我的用法有问题,我的代码如下:

    func main() {
        r := config.New("yyyy")
        r.WithOptions(config.ParseEnv)
    
        r.AddDriver(ini.Driver)
    
        err := r.LoadFiles("yyyy.ini")
        if err != nil {
            panic(err)
        }
    
        fmt.Printf("config data: \n %#v\n", r.Data())
    
        f, e := os.OpenFile("xxxx.ini", os.O_RDWR|os.O_CREATE, 0666)
        if e != nil {
            fmt.Println(e)
            return
        }
        defer f.Close()
    
        n, e := r.DumpTo(f, config.Ini)
        fmt.Println(n, e)
    }
    
  • Add http://  Support

    Add http:// Support

    	"address": [
    		"192.168.1.XXX:2379",
    		"192.168.1.XXX:2379",
    		"192.168.1.XXX:2379"
    	]
    

    is OK, but "address": [ "http://192.168.1.XXX:2379", "http://192.168.1.XXX:2379", "http://192.168.1.XXX:2379" ] is panic. panic: ReadString: invalid control character found: 10, error found in #10 byte of ...|79" Strings containing “http://” are very common, Don't be confused with comments。 Tanks.

  • Add Duration type support

    Add Duration type support

    conf.Duration(key) = time.Duration
    ---
    Save Steps:
      timeout := time.Duration(Conf.Int64("timeout"))
      timeoutDuration := time.Second * timeout 
    
  • build(deps): bump github.com/gookit/properties from 0.1.0 to 0.2.0

    build(deps): bump github.com/gookit/properties from 0.1.0 to 0.2.0

    Bumps github.com/gookit/properties from 0.1.0 to 0.2.0.

    Release notes

    Sourced from github.com/gookit/properties's releases.

    v0.2.0

    Change Log

    Feature

    Other

    Commits
    • 9fcffad test: add any define for test on go < 1.18
    • c38278e chore: revert x/sys version for go < 1.17
    • 9499e03 dep: update the dep gookit/goutil to latest
    • afc8f85 chore: update readme add more usage docs
    • 0fb7060 feat: complete support encode map or struct data to properties text
    • bd35eb9 chore: update readme and update some deps
    • 6cb871a Merge pull request #2 from gookit/dependabot/go_modules/github.com/gookit/gou...
    • 6805185 build(deps): bump github.com/gookit/goutil from 0.5.9 to 0.5.10
    • See full diff in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • build(deps): bump github.com/gookit/ini/v2 from 2.1.1 to 2.1.2

    build(deps): bump github.com/gookit/ini/v2 from 2.1.1 to 2.1.2

    Bumps github.com/gookit/ini/v2 from 2.1.1 to 2.1.2.

    Release notes

    Sourced from github.com/gookit/ini/v2's releases.

    v2.1.2

    Change Log

    Fixed

    Update

    Other

    Commits
    • 7df8e94 up: add more unit tests, remove dep stretchr/testify
    • c8a8ab2 chore: update readme and go version limit
    • 77c6467 up: pref some read and write config logic
    • 319f605 Merge pull request #52 from gookit/dependabot/go_modules/github.com/gookit/go...
    • 92aee19 build(deps): bump github.com/gookit/goutil from 0.5.11 to 0.5.12
    • 162a8a6 Merge pull request #51 from gookit/dependabot/go_modules/github.com/gookit/go...
    • 8d7adaa build(deps): bump github.com/gookit/goutil from 0.5.10 to 0.5.11
    • dfbd709 Merge pull request #50 from gookit/dependabot/go_modules/github.com/gookit/go...
    • 8eb45c4 build(deps): bump github.com/gookit/goutil from 0.5.9 to 0.5.10
    • 63f2755 Merge pull request #49 from gookit/dependabot/go_modules/github.com/gookit/go...
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • Support slice with ParseEnv

    Support slice with ParseEnv

    System (please complete the following information):

    • OS: linux
    • GO Version: 1.19.4
    • Pkg Version: 2.1.8

    Describe the bug

    Slice not parser with environment variables.

    To Reproduce

    package main
    
    import (
    	"github.com/gookit/config/v2"
    )
    
    var version = "dev"
    
    type conf struct {
    	Name  string   `mapstructure:"name" default:"${NAME | Bob}"`
    	Value []string `mapstructure:"value" default:"${VAL | val1}"`
    }
    
    func main() {
    
    	config.WithOptions(
    		config.ParseDefault,
    		config.ParseEnv,
    		config.Readonly,
    	)
    
    	err := config.LoadExists("")
    	if err != nil {
    		panic(err)
    	}
    
    	var cc conf
    	if err := config.Decode(&cc); err != nil {
    		panic(err)
    	}
    }
    

    Actual behavior

    panic: convert value type error
    
    goroutine 1 [running]:
    main.main()
            /run/media/unikum/UNIKUM-STORAGE/work/centrofinans/dev/kafka-tb-translator/tools/conf/main.go:29 +0xd1
    exit status 2
    
  • build(deps): bump github.com/gookit/goutil from 0.5.15 to 0.6.1

    build(deps): bump github.com/gookit/goutil from 0.5.15 to 0.6.1

    Bumps github.com/gookit/goutil from 0.5.15 to 0.6.1.

    Release notes

    Sourced from github.com/gookit/goutil's releases.

    v0.6.1

    Change Log

    Feature

    Update

    Other

    What's Changed

    New Contributors

    Full Changelog: https://github.com/gookit/goutil/compare/v0.6.0...v0.6.1

    v0.6.0

    Change Log

    NOTE: since v0.6.0 require go 1.18

    Refactor

    Feature

    ... (truncated)

    Commits
    • a55c5ca :sparkles: feat(dump): support skip nil field dump on map, struct by option S...
    • bc0a0b8 :bulb: chore: add comment for exported vars, methods.
    • 179afea :sparkles: feat(structs): add new util func for check struct field is exported
    • 025464a :sparkles: feat(dump): support dump []byte as string and more new options
    • 31b8753 Merge pull request #75 from huangkuan123/SubstrCount
    • 1bff3b3 add SubstrCount and test case.
    • ea10bc7 :bulb: chore: add exported var comment, fix some name style
    • 6ace647 :bulb: chore: add package comment or exported var comment
    • c38e08e Merge pull request #73 from gookit/dependabot/go_modules/golang.org/x/text-0.5.0
    • c3f5086 chore: update some readme and re-generate readme docs
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • ReloadFiles方法在重载json格式的文件时会发生错误但toml正常

    ReloadFiles方法在重载json格式的文件时会发生错误但toml正常

    // 监听配置文件热修改
    func watchConfigFiles(cfg *config.Config) {
    	// 开一个新线程防止主线程被卡住
    	readyTask := new(sync.WaitGroup)
    	readyTask.Add(1)
    	go func() {
    		watcher, err := fsnotify.NewWatcher()
    		if err != nil {
    			cliutil.Errorln(err.Error())
    			return
    		}
    		defer watcher.Close()
    		// 获取加载的配置文件
    		files := cfg.LoadedFiles()
    		if len(files) == 0 {
    			cliutil.Errorln("未读取到配置文件")
    			return
    		}
    
    		// 处理出错或通道关闭时的退出问题
    		eventsTask := new(sync.WaitGroup)
    		eventsTask.Add(1)
    		go func() {
    			for {
    				select {
    				case event, ok := <-watcher.Events:
    					if !ok {
    						eventsTask.Done()
    						return
    					}
    					// 只有写入时才重新创建数据
    					switch event.Op.String() {
    					case "WRITE":
    						// 重载数据
    						if err := cfg.ReloadFiles(); err != nil {
    							eventsTask.Done()
    							cliutil.Errorf("重载%s数据出错,err:%s\n", event.Name, err.Error())
    							return
    						}
    						cliutil.Infof("监听到%s变动\n", event.Name)
    						fmt.Println(cfg.Data())
    					case "REMOVE":
    						eventsTask.Done()
    						cliutil.Errorf("重载%s数据出错,err:文件被删除,请不要删除配置文件\n", event.Name)
    						return
    					default:
    						cliutil.Infof("监听到%s变动 Op->%s\n", event.Name, event.Op.String())
    					}
    				case err, ok := <-watcher.Errors:
    					if ok {
    						cliutil.Errorln(err.Error())
    					}
    					if err != nil {
    						cliutil.Errorln(err.Error())
    					}
    					eventsTask.Done()
    					return
    				}
    			}
    		}()
    		// 加载文件的监听
    		for _, path := range files {
    			if err := watcher.Add(path); err != nil {
    				cliutil.Errorln(err.Error())
    			}
    		}
    		// 加载文件监听成功后释放创建监听的线程
    		readyTask.Done()
    		// 等待事件释放
    		eventsTask.Wait()
    	}()
    	// 等待监听成功
    	readyTask.Wait()
    }
    

    以上是监听代码

    json文件使用的是github.com/gookit/config/v2/json这个驱动 toml文件使用的是github.com/gookit/config/v2/toml这个驱动

    出错时报的错误:ReadMapCB: expect { or n, but found , error found in #0 byte of ...||..., bigger context ...||...

    json格式的数据

    {
      "app": {
        "name": "ceshi",
        "mode": "debug2"
      }
    }
    

    toml格式的数据

    [app]
    name = "ceshi"
    mode = "debug"
    
  • build(deps): bump github.com/hashicorp/hcl/v2 from 2.14.1 to 2.15.0

    build(deps): bump github.com/hashicorp/hcl/v2 from 2.14.1 to 2.15.0

    Bumps github.com/hashicorp/hcl/v2 from 2.14.1 to 2.15.0.

    Release notes

    Sourced from github.com/hashicorp/hcl/v2's releases.

    v2.15.0

    Bugs Fixed

    • ext/typeexpr: Skip null objects when applying defaults. This prevents crashes when null objects are creating inside collections, and stops incomplete objects being created with only optional attributes set. (#567)
    • ext/typeexpr: Ensure default values do not have optional metadata attached. This prevents crashes when default values are inserted into concrete go-cty values that have also been stripped of their optional metadata. (#568)

    Enhancements

    • ext/typeexpr: With the go-cty upstream depenendency updated to v1.12.0, the Defaults struct and associated functions can apply additional and more flexible 'unsafe' conversions (examples include tuples into collections such as lists and sets, and additional safety around null and dynamic values). (#564)
    • ext/typeexpr: With the go-cty upstream depenendency updated to v1.12.0, users should now apply the go-cty convert functionality before setting defaults on a given cty.Value, rather than after, if they require a specific cty.Type. (#564)
    Changelog

    Sourced from github.com/hashicorp/hcl/v2's changelog.

    v2.15.0 (November 10, 2022)

    Bugs Fixed

    • ext/typeexpr: Skip null objects when applying defaults. This prevents crashes when null objects are creating inside collections, and stops incomplete objects being created with only optional attributes set. (#567)
    • ext/typeexpr: Ensure default values do not have optional metadata attached. This prevents crashes when default values are inserted into concrete go-cty values that have also been stripped of their optional metadata. (#568)

    Enhancements

    • ext/typeexpr: With the go-cty upstream depenendency updated to v1.12.0, the Defaults struct and associated functions can apply additional and more flexible 'unsafe' conversions (examples include tuples into collections such as lists and sets, and additional safety around null and dynamic values). (#564)
    • ext/typeexpr: With the go-cty upstream depenendency updated to v1.12.0, users should now apply the go-cty convert functionality before setting defaults on a given cty.Value, rather than after, if they require a specific cty.Type. (#564)
    Commits
    • 31e2c60 Release v2.15.0
    • 07502d3 Update CHANGELOG.md
    • bcff50c Strip optional metadata from empty default collections (#568)
    • fa90633 Update CHANGELOG.md
    • b6727bf Merge pull request #567 from liamcervante/terraform/32157
    • 233ef62 add test cases that verify behaviour from the forums
    • c7cfb6a remove previous complex test cases
    • d29499f don't insert default values into null objects
    • e86af16 Merge pull request #566 from hashicorp/liamcervante/changelog
    • ba75ecb Update CHANGELOG.md
    • Additional commits viewable in compare view

    Dependabot compatibility score

    Dependabot will resolve any conflicts with this PR as long as you don't alter it yourself. You can also trigger a rebase manually by commenting @dependabot rebase.


    Dependabot commands and options

    You can trigger Dependabot actions by commenting on this PR:

    • @dependabot rebase will rebase this PR
    • @dependabot recreate will recreate this PR, overwriting any edits that have been made to it
    • @dependabot merge will merge this PR after your CI passes on it
    • @dependabot squash and merge will squash and merge this PR after your CI passes on it
    • @dependabot cancel merge will cancel a previously requested merge and block automerging
    • @dependabot reopen will reopen this PR if it is closed
    • @dependabot close will close this PR and stop Dependabot recreating it. You can achieve the same result by closing it manually
    • @dependabot ignore this major version will close this PR and stop Dependabot creating any more for this major version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this minor version will close this PR and stop Dependabot creating any more for this minor version (unless you reopen the PR or upgrade to it yourself)
    • @dependabot ignore this dependency will close this PR and stop Dependabot creating any more for this dependency (unless you reopen the PR or upgrade to it yourself)
  • [FEAT] Support Encrypted Config File

    [FEAT] Support Encrypted Config File

    It would be nice to have a built-in encrypted config file so sometime we are only allow user to change setting directly from the app.

    I have 2 function to encrypt and decrypt the string to base64, just not sure how to implement it...

    // Encrypt a string with a secret key.
    // Secretkey must be 16, 24 or 32 characters long.
    func EncryptStr(text, secretKey string) (string, error) {
    	var randBytes = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}
    	block, err := aes.NewCipher([]byte(secretKey))
    	if err != nil {
    		return "", err
    	}
    	plainText := []byte(text)
    	cfb := cipher.NewCFBEncrypter(block, randBytes)
    	cipherText := make([]byte, len(plainText))
    	cfb.XORKeyStream(cipherText, plainText)
    	endCodeCipherText := base64.StdEncoding.EncodeToString(cipherText)
    	return endCodeCipherText, nil
    }
    
    // Decrypt am encrypt string with the same secret key used in encrypt.
    // Secretkey must be 16, 24 or 32 characters long.
    func DecryptStr(eText, secretKey string) (string, error) {
    	var randBytes = []byte{35, 46, 57, 24, 85, 35, 24, 74, 87, 35, 88, 98, 66, 32, 14, 05}
    	block, err := aes.NewCipher([]byte(secretKey))
    	if err != nil {
    		return "", err
    	}
    	cipherText, _ := base64.StdEncoding.DecodeString(eText)
    	cfb := cipher.NewCFBDecrypter(block, randBytes)
    	plainText := make([]byte, len(cipherText))
    	cfb.XORKeyStream(plainText, cipherText)
    	return string(plainText), nil
    }
    

    Thought?

Library providing routines to merge and validate JSON, YAML and/or TOML files
Library providing routines to merge and validate JSON, YAML and/or TOML files

CONFLATE Library providing routines to merge and validate JSON, YAML, TOML files and/or structs (godoc) Typical use case: Make your application config

Sep 26, 2022
Package ini provides INI file read and write functionality in Go.

INI Package ini provides INI file read and write functionality in Go. Features Load from multiple data sources(file, []byte, io.Reader and io.ReadClos

Dec 29, 2022
Tmpl - A tool to apply variables from cli, env, JSON/TOML/YAML files to templates

tmpl allows to apply variables from JSON/TOML/YAML files, environment variables or CLI arguments to template files using Golang text/template and functions from the Sprig project.

Nov 14, 2022
Generic templating tool with support of JSON, YAML and TOML data

gotempl Small binary used to generate files from Go Templates and data files. The following formats are supported: JSON YAML TOML Usage usage: gotempl

Jun 15, 2022
Golang Configuration tool that support YAML, JSON, TOML, Shell Environment

Configor Golang Configuration tool that support YAML, JSON, TOML, Shell Environment (Supports Go 1.10+) Usage package main import ( "fmt" "github.c

Dec 29, 2022
Go-config - Config parser for go that supports environment vars and multiple yaml files

go-multiconfig This package is able to parse yaml config files. It supports gett

Jun 23, 2022
⚙️ Dead Simple Config Management, load and persist config without having to think about where and how.

Configo Dead Simple Config Management, load and persist config without having to think about where and how. Install go get github.com/UltiRequiem/conf

Apr 6, 2022
A Go (golang) environment loader (which loads env vars from a .env file)

A Go (golang) environment loader (which loads env vars from a .env file)

Feb 8, 2022
Quick and easy way to load config files based on a simple set of rules.
Quick and easy way to load config files based on a simple set of rules.

config Quick and easy way to load config files based on a simple set of rules. Project inspired by https://github.com/lorenwest/node-config Important

Apr 9, 2021
Library for setting values to structs' fields from env, flags, files or default tag

Configuration is a library for injecting values recursively into structs - a convenient way of setting up a configuration object. Available features:

Dec 7, 2022
A simple INI file parser and builder.

ini A simple INI file parser and builder. What Read INI files, or build them section by section. Datatypes are kept very simple. The main fuctions are

Nov 20, 2021
HCL is the HashiCorp configuration language.

HCL HCL is a toolkit for creating structured configuration languages that are both human- and machine-friendly, for use with command-line tools. Altho

Jan 9, 2023
create a bootable disk image from Docker image or a yaml config

docker2boot docker2boot creates a bootable disk from either a Docker image or a config yaml file Features status dns Y cloud-init Y network Y ssh TODO

Oct 30, 2022
Golang config.yaml loader

Description goconfig is a configuration library designed using the following pri

May 31, 2022
Go-yaml - Yaml parsing Toolkit For Golang

go-yaml 介绍 gopkg.in/yaml.v3 已经是个非常好用的包,但是在实际开发中总有类型转换带来的麻烦,go-yaml只是在它的基础上,简单的一层

Jan 13, 2022
A golang package for parsing ini-style configuration files

Mini Mini is a simple ini configuration file parser. The ini syntax supported includes: The standard name=value Comments on new lines starting with #

Jan 7, 2023
ini parser for golang
ini parser for golang

INI Parser & Write Library ini parser and write library for Golang,easy-use,fast Features Can be read by []byte Can be read by file Supports file moni

Dec 3, 2022
Tinyini - Bare-bones Go library for reading INI-like configuration files

tinyini tinyini is a minimalistic library for parsing INI-like configuration files. example configuration file globalkey = globalvalue [section] key

Jan 10, 2022
INI Loader written in Go

go-ini INI Loader written in Go Single threaded & simple Examples Read all params func (app MyApp) onParam(name string, value string) bool { app.c

Feb 11, 2022