gconf

package module
v4.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: May 12, 2020 License: Apache-2.0 Imports: 28 Imported by: 1

README

gconf Build Status GoDoc License

An extensible and powerful go configuration manager, which is inspired by oslo.config, github.com/micro/go-micro/config and viper.

The current version is v4 to support Semantic Import Versioning, which requires Go1.11+. See DOC.

Install

$ go get -u github.com/xgfone/gconf/v4
V3
$ go1.x  get -u github.com/xgfone/gconf
$ go1.11 get -u github.com/xgfone/gconf@v3.7.0
$ go1.12 get -u github.com/xgfone/gconf@v3.7.0
$ GONOSUMDB="*" go1.13 get -u github.com/xgfone/gconf@v3.7.0

Goal

  1. A atomic key-value configuration center with the multi-group and the option.
  2. Support the multi-parser to parse the configurations from many sources with the different format.
  3. Change the configuration dynamically during running and watch it.
  4. Observe the change of the configuration.
  5. All of operations are atomic.

Source

Source is used to read the configuration data. You can load lots of sources to read the configuration data from many storage locations. The default has implemented some sources, such as flag, cli, env, file, url, zookeeper. But you can also implement other sources, such as ETCD, etc.

Notice: If the source supports the watcher, it will add it to watch the changed of the source data automatically.

Decoder

The source reads the original data, that's []byte, and it must be decoded. The default has implemented the json, yaml, toml and INI decoders.

Read and Update the option value

You can get the group or sub-group by calling Group(name), then get the option value again by calling GetBool("optionName"), GetString("optionName"), GetInt("optionName"), etc. However, if you don't known whether the option has a value, you can call Get("optionName"), which returns nil if no option or value, etc.

Beside, you can update the value of the option dynamically by calling UpdateOptValue(groupFullName, optName, newOptValue) during the program is running. For the default group, groupFullName is a empty string("").

Notce:

  1. Both of Reading and Updating are goroutine-safe.
  2. For the modifiable type, such as slice or map, in order to update them, you should clone them firstly, then update the cloned option vlaue and call UpdateOptValue with it.

Observe the changed configuration

You can use the method Observe(callback func(groupName, optName string, oldOptValue, newOptValue interface{})) to monitor what the configuration is updated to: when a certain configuration is updated, the callback function will be called synchronizedly.

Usage

package main

import (
	"flag"
	"fmt"

	"github.com/xgfone/gconf/v4"
)

func main() {
	// Register options
	conf := gconf.New()
	conf.RegisterOpt(gconf.StrOpt("ip", "the ip address").D("0.0.0.0").V(gconf.NewIPValidator()))
	conf.RegisterOpt(gconf.IntOpt("port", "the port").D(80))
	conf.NewGroup("redis").RegisterOpt(gconf.StrOpt("conn", "the redis connection url"))

	// Set the CLI version and exit when giving the CLI option version.
	conf.SetVersion(gconf.VersionOpt.D("1.0.0"))
	gconf.AddAndParseOptFlag(conf)

	// Load the sources
	conf.LoadSource(gconf.NewFlagSource())

	// Read and print the option
	fmt.Println(conf.GetString("ip"))
	fmt.Println(conf.GetInt("port"))
	fmt.Println(conf.Group("redis").GetString("conn"))
	fmt.Println(flag.Args())

	// Execute:
	//     PROGRAM --ip 1.2.3.4 --redis.conn=redis://127.0.0.1:6379/0 aa bb cc
	//
	// Output:
	//     1.2.3.4
	//     80
	//     redis://127.0.0.1:6379/0
	//     [aa bb cc]
}

The package has created a global default Config, that's, Conf. You can use it, like the global variable CONF in oslo.config. Besides, the package exports some methods of Conf as the global functions, and you can use them. For example,

package main

import (
	"fmt"

	"github.com/xgfone/gconf/v4"
)

var opts = []gconf.Opt{
	gconf.StrOpt("ip", "the ip address").D("0.0.0.0").V(gconf.NewIPValidator()),
	gconf.IntOpt("port", "the port").D(80).V(gconf.NewPortValidator()),
}

func main() {
	// Register options
	gconf.RegisterOpts(opts)

	// Add the options to flag.CommandLine and parse the CLI
	gconf.AddAndParseOptFlag(gconf.Conf)

	// Load the sources
	gconf.LoadSource(gconf.NewFlagSource())

	// Read and print the option
	fmt.Println(gconf.GetString("ip"))
	fmt.Println(gconf.GetInt("port"))

	// Execute:
	//     PROGRAM --ip 1.2.3.4
	//
	// Output:
	//     1.2.3.4
	//     80
}

You can watch the change of the configuration option.

package main

import (
	"fmt"
	"time"

	"github.com/xgfone/gconf/v4"
)

func main() {
	// Register the options
	gconf.RegisterOpt(gconf.StrOpt("opt1", "").D("abc"))
	gconf.NewGroup("group").RegisterOpt(gconf.IntOpt("opt2", "").D(123))

	// Add the observer
	gconf.Observe(func(group, opt string, old, new interface{}) {
		fmt.Printf("[Observer] Setting: group=%s, opt=%s, old=%v, new=%v\n", group, opt, old, new)
	})

	// Update the value of the option.
	gconf.UpdateOptValue("", "opt1", "xyz") // The first way
	gconf.Group("group").Set("opt2", 789)   // The second way

	// Output:
	// [Observer] Setting: group=, opt=opt1, old=abc, new=xyz
	// [Observer] Setting: group=group, opt=opt2, old=123, new=789
}
The cli Command

The flag does not support the command, so you can use github.com/urfave/cli.

package main

import (
	"fmt"

	"github.com/urfave/cli"
	"github.com/xgfone/gconf/v4"
)

func main() {
	// Register options into the group
	gconf.RegisterOpt(gconf.StrOpt("opt1", "").D("abc"))
	gconf.NewGroup("cmd1").RegisterOpt(gconf.IntOpt("opt2", ""))
	gconf.NewGroup("cmd1.cmd2").RegisterOpt(gconf.IntOpt("opt3", ""))

	// Create and run cli app.
	app := cli.NewApp()
	app.Flags = gconf.ConvertOptsToCliFlags(gconf.Conf.OptGroup)
	app.Commands = []cli.Command{
		cli.Command{
			Name:  "cmd1",
			Flags: gconf.ConvertOptsToCliFlags(gconf.Group("cmd1")),
			Subcommands: []cli.Command{
				cli.Command{
					Name:  "cmd2",
					Flags: gconf.ConvertOptsToCliFlags(gconf.Group("cmd1.cmd2")),
					Action: func(ctx *cli.Context) error {
						// Load the sources
						gconf.LoadSource(gconf.NewCliSource(ctx, "cmd1.cmd2"))      // cmd2
						gconf.LoadSource(gconf.NewCliSource(ctx.Parent(), "cmd1"))  // cmd1
						gconf.LoadSource(gconf.NewCliSource(ctx.Parent().Parent())) // global

						// Read and print the option
						fmt.Println(gconf.GetString("opt1"))
						fmt.Println(gconf.Group("cmd1").GetInt("opt2"))
						fmt.Println(gconf.Group("cmd1.cmd2").GetInt("opt3"))

						return nil
					},
				},
			},
		},
	}
	app.RunAndExitOnError()

	// Execute:
	//     PROGRAM --opt1=xyz cmd1 --opt2=123 cmd2 --opt3=456
	//
	// Output:
	//     xyz
	//     123
	//     456
}
Use the config file

The default file source supports watcher, it will watch the change of the given filename then reload it.

package main

import (
	"fmt"
	"time"

	"github.com/xgfone/gconf/v4"
)

var opts = []gconf.Opt{
	gconf.StrOpt("ip", "the ip address").D("0.0.0.0").V(gconf.NewIPValidator()),
	gconf.IntOpt("port", "the port").D(80).V(gconf.NewPortValidator()),
}

func main() {
	// Register options
	//
	// Notice: the default global Conf has registered gconf.O.
	gconf.RegisterOpts(opts)

	// Add the options to flag.CommandLine and parse the CLI
	gconf.AddAndParseOptFlag(gconf.Conf)

	// Load the flag & file sources
	gconf.LoadSource(gconf.NewFlagSource())
	gconf.LoadSource(gconf.NewFileSource(gconf.GetString(gconf.ConfigFileOpt.Name)))

	// Read and print the option
	for {
		time.Sleep(time.Second * 10)
		fmt.Printf("%s:%d\n", gconf.GetString("ip"), gconf.GetInt("port"))
	}

	// $ PROGRAM --config-file /path/to/config.json &
	// 0.0.0.0:80
	//
	// $ echo '{"ip": "1.2.3.4", "port": 8000}' >/path/to/config.json
	// 1.2.3.4:8000
	//
	// $ echo '{"ip": "5.6.7.8", "port":9 000}' >/path/to/config.json
	// 5.6.7.8:9000
}

Notice: Because there are four kinds of default decoders, json, yaml, toml and INI, the file is only one of them. But you can register other decoders to support more format files.

Register a struct as the group and the option

You also register a struct then use it.

package main

import (
	"fmt"
	"os"
	"time"

	"github.com/xgfone/gconf/v4"
)

type Group struct {
	Bool     bool          `help:"test bool"`
	Int      int           `default:"123" help:"test int"`
	Int32    int32         `default:"123" help:"test int32"`
	Int64    int64         `default:"123" help:"test int64"`
	Uint     uint          `default:"123" help:"test uint"`
	Uint32   uint32        `default:"123" help:"test uint32"`
	Uint64   uint64        `default:"123" help:"test uint64"`
	Float64  float64       `default:"123" help:"test float64"`
	String   string        `default:"abc" help:"test string"`
	Duration time.Duration `default:"123s" help:"test time.Duration"`
	Time     time.Time     `help:"test time.Time"`

	Ints      []int           `default:"1,2,3" help:"test []int"`
	Uints     []uint          `default:"1,2,3" help:"test []uint"`
	Float64s  []float64       `default:"1,2,3" help:"test []float64"`
	Strings   []string        `default:"a,b,c" help:"test []string"`
	Durations []time.Duration `default:"1s,2s,3s" help:"test []time.Duration"`
}

type WrapGroup struct {
	Bool     bool          `help:"test bool"`
	Int      int           `default:"456" help:"test int"`
	Int32    int32         `default:"456" help:"test int32"`
	Int64    int64         `default:"456" help:"test int64"`
	Uint     uint          `default:"456" help:"test uint"`
	Uint32   uint32        `default:"456" help:"test uint32"`
	Uint64   uint64        `default:"456" help:"test uint64"`
	Float64  float64       `default:"456" help:"test float64"`
	String   string        `default:"efg" help:"test string"`
	Duration time.Duration `default:"456s" help:"test time.Duration"`
	Time     time.Time     `help:"test time.Time"`

	Ints      []int           `default:"4,5,6" help:"test []int"`
	Uints     []uint          `default:"4,5,6" help:"test []uint"`
	Float64s  []float64       `default:"4,5,6" help:"test []float64"`
	Strings   []string        `default:"e,f,g" help:"test []string"`
	Durations []time.Duration `default:"4s,5s,6s" help:"test []time.Duration"`

	Group Group `group:"group3" name:"group33"`
}

type DataConfig struct {
	Bool     bool          `help:"test bool"`
	Int      int           `default:"789" help:"test int"`
	Int32    int32         `default:"789" help:"test int32"`
	Int64    int64         `default:"789" help:"test int64"`
	Uint     uint          `default:"789" help:"test uint"`
	Uint32   uint32        `default:"789" help:"test uint32"`
	Uint64   uint64        `default:"789" help:"test uint64"`
	Float64  float64       `default:"789" help:"test float64"`
	String   string        `default:"xyz" help:"test string"`
	Duration time.Duration `default:"789s" help:"test time.Duration"`
	Time     time.Time     `help:"test time.Time"`

	Ints      []int           `default:"7,8,9" help:"test []int"`
	Uints     []uint          `default:"7,8,9" help:"test []uint"`
	Float64s  []float64       `default:"7,8,9" help:"test []float64"`
	Strings   []string        `default:"x,y,z" help:"test []string"`
	Durations []time.Duration `default:"7s,8s,9s" help:"test []time.Duration"`

	Group1 Group     `group:"group1"`
	Group2 WrapGroup `name:"group2"`
}

func main() {
	// Register the option from struct
	var data DataConfig
	conf := gconf.New()
	conf.RegisterStruct(&data)

	// Add options to flag, and parse them from flag.
	gconf.AddAndParseOptFlag(conf)
	conf.LoadSource(gconf.NewFlagSource())

	fmt.Println("--- Struct ---")
	fmt.Printf("bool: %t\n", data.Bool)
	fmt.Printf("int: %d\n", data.Int)
	fmt.Printf("int32: %d\n", data.Int32)
	fmt.Printf("int64: %d\n", data.Int64)
	fmt.Printf("uint: %d\n", data.Uint)
	fmt.Printf("uint32: %d\n", data.Uint32)
	fmt.Printf("uint64: %d\n", data.Uint64)
	fmt.Printf("float64: %v\n", data.Float64)
	fmt.Printf("string: %s\n", data.String)
	fmt.Printf("duration: %s\n", data.Duration)
	fmt.Printf("time: %s\n", data.Time)
	fmt.Printf("ints: %v\n", data.Ints)
	fmt.Printf("uints: %v\n", data.Uints)
	fmt.Printf("float64s: %v\n", data.Float64s)
	fmt.Printf("strings: %v\n", data.Strings)
	fmt.Printf("durations: %v\n", data.Durations)
	// ...
	fmt.Println("--- Config ---")
	fmt.Printf("bool: %t\n", conf.GetBool("bool"))
	fmt.Printf("int: %d\n", conf.GetInt("int"))
	fmt.Printf("int32: %d\n", conf.GetInt32("int32"))
	fmt.Printf("int64: %d\n", conf.GetInt64("int64"))
	fmt.Printf("uint: %d\n", conf.GetUint("uint"))
	fmt.Printf("uint32: %d\n", conf.GetUint32("uint32"))
	fmt.Printf("uint64: %d\n", conf.GetUint64("uint64"))
	fmt.Printf("float64: %v\n", conf.GetFloat64("float64"))
	fmt.Printf("string: %s\n", conf.GetString("string"))
	fmt.Printf("duration: %s\n", conf.GetDuration("duration"))
	fmt.Printf("time: %s\n", conf.GetTime("time"))
	fmt.Printf("ints: %v\n", conf.GetIntSlice("ints"))
	fmt.Printf("uints: %v\n", conf.GetUintSlice("uints"))
	fmt.Printf("float64s: %v\n", conf.GetFloat64Slice("float64s"))
	fmt.Printf("strings: %v\n", conf.GetStringSlice("strings"))
	fmt.Printf("durations: %v\n", conf.GetDurationSlice("durations"))
	// ...
	fmt.Println("--- Group ---")
	conf.PrintGroup(os.Stdout)

	// RUN:
	//     PROGRAM --bool=true --time=2019-06-11T20:00:00Z --group1.bool=1
	//
	// Output:
	//     --- Struct ---
	//     bool: true
	//     int: 789
	//     int32: 789
	//     int64: 789
	//     uint: 789
	//     uint32: 789
	//     uint64: 789
	//     float64: 789
	//     string: xyz
	//     duration: 13m9s
	//     time: 2019-06-11 20:00:00 +0000 UTC
	//     ints: [7 8 9]
	//     uints: [7 8 9]
	//     float64s: [7 8 9]
	//     strings: [x y z]
	//     durations: [7s 8s 9s]
	//     --- Config ---
	//     bool: true
	//     int: 789
	//     int32: 789
	//     int64: 789
	//     uint: 789
	//     uint32: 789
	//     uint64: 789
	//     float64: 789
	//     string: xyz
	//     duration: 13m9s
	//     time: 2019-06-11 20:00:00 +0000 UTC
	//     ints: [7 8 9]
	//     uints: [7 8 9]
	//     float64s: [7 8 9]
	//     strings: [x y z]
	//     durations: [7s 8s 9s]
	//     --- Group ---
	//     [DEFAULT]
	//         bool
	//         duration
	//         durations
	//         float64
	//         float64s
	//         int
	//         int32
	//         int64
	//         ints
	//         string
	//         strings
	//         time
	//         uint
	//         uint32
	//         uint64
	//         uints
	//     [group1]
	//         bool
	//         duration
	//         durations
	//         float64
	//         float64s
	//         int
	//         int32
	//         int64
	//         ints
	//         string
	//         strings
	//         time
	//         uint
	//         uint32
	//         uint64
	//         uints
	//     [group2]
	//         bool
	//         duration
	//         durations
	//         float64
	//         float64s
	//         int
	//         int32
	//         int64
	//         ints
	//         string
	//         strings
	//         time
	//         uint
	//         uint32
	//         uint64
	//         uints
	//     [group2.group3]
	//         bool
	//         duration
	//         durations
	//         float64
	//         float64s
	//         int
	//         int32
	//         int64
	//         ints
	//         string
	//         strings
	//         time
	//         uint
	//         uint32
	//         uint64
	//         uints
}

For the base types and their slice types, it's not goroutine-safe to get or set the value of the struct field. But you can use the versions of their OptField instead.

package main

import (
	"fmt"
	"time"

	"github.com/xgfone/gconf/v4"
)

// AppConfig is used to configure the application.
type AppConfig struct {
	Bool      gconf.BoolOptField
	BoolT     gconf.BoolTOptField
	Int       gconf.IntOptField
	Int32     gconf.Int32OptField
	Int64     gconf.Int64OptField
	Uint      gconf.UintOptField
	Uint32    gconf.Uint32OptField
	Uint64    gconf.Uint64OptField
	Float64   gconf.Float64OptField
	String    gconf.StringOptField
	Duration  gconf.DurationOptField
	Time      gconf.TimeOptField
	Ints      gconf.IntSliceOptField
	Uints     gconf.UintSliceOptField
	Float64s  gconf.Float64SliceOptField
	Strings   gconf.StringSliceOptField
	Durations gconf.DurationSliceOptField

	// Pointer Example
	IntP   *gconf.IntOptField `default:"123" short:"i" help:"test int pointer"`
	Ignore *gconf.StringOptField
}

func main() {
	// Notice: for the pointer to the option field, it must be initialized.
	// Or it will be ignored.
	config := AppConfig{IntP: &gconf.IntOptField{}}
	conf := gconf.New()
	conf.RegisterStruct(&config)

	fmt.Println("--- Registered Options ---")
	for _, opt := range conf.AllOpts() {
		fmt.Println(opt.Name)
	}

	fmt.Println("--- Before Updating ---")
	fmt.Printf("bool=%v\n", config.Bool.Get())
	fmt.Printf("boolt=%v\n", config.BoolT.Get())
	fmt.Printf("int=%v\n", config.Int.Get())
	fmt.Printf("int32=%v\n", config.Int32.Get())
	fmt.Printf("int64=%v\n", config.Int64.Get())
	fmt.Printf("uint=%v\n", config.Uint.Get())
	fmt.Printf("uint32=%v\n", config.Uint32.Get())
	fmt.Printf("uint64=%v\n", config.Uint64.Get())
	fmt.Printf("float64=%v\n", config.Float64.Get())
	fmt.Printf("string=%v\n", config.String.Get())
	fmt.Printf("duration=%v\n", config.Duration.Get())
	fmt.Printf("time=%v\n", config.Time.Get().Format(time.RFC3339))
	fmt.Printf("ints=%v\n", config.Ints.Get())
	fmt.Printf("uints=%v\n", config.Uints.Get())
	fmt.Printf("float64s=%v\n", config.Float64s.Get())
	fmt.Printf("strings=%v\n", config.Strings.Get())
	fmt.Printf("durations=%v\n", config.Durations.Get())
	fmt.Printf("intp=%v\n", config.IntP.Get())

	conf.Set("bool", true)
	conf.Set("boolt", false)
	conf.Set("int", 123)
	conf.Set("int32", 123)
	conf.Set("int64", 123)
	conf.Set("uint", 123)
	conf.Set("uint32", 123)
	conf.Set("uint64", 123)
	conf.Set("float64", 123)
	conf.Set("string", "abc")
	conf.Set("duration", "10s")
	conf.Set("time", "2019-07-27 15:39:34")
	conf.Set("ints", []int{1, 2, 3})
	conf.Set("uints", []uint{4, 5, 6})
	conf.Set("float64s", []float64{1, 2, 3})
	conf.Set("strings", []string{"a", "b", "c"})
	conf.Set("durations", []time.Duration{time.Second, time.Second * 2, time.Second * 3})
	conf.Set("intp", 456)

	fmt.Println("--- After Updating ---")
	fmt.Printf("bool=%v\n", config.Bool.Get())
	fmt.Printf("boolt=%v\n", config.BoolT.Get())
	fmt.Printf("int=%v\n", config.Int.Get())
	fmt.Printf("int32=%v\n", config.Int32.Get())
	fmt.Printf("int64=%v\n", config.Int64.Get())
	fmt.Printf("uint=%v\n", config.Uint.Get())
	fmt.Printf("uint32=%v\n", config.Uint32.Get())
	fmt.Printf("uint64=%v\n", config.Uint64.Get())
	fmt.Printf("float64=%v\n", config.Float64.Get())
	fmt.Printf("string=%v\n", config.String.Get())
	fmt.Printf("duration=%v\n", config.Duration.Get())
	fmt.Printf("time=%v\n", config.Time.Get().Format(time.RFC3339))
	fmt.Printf("ints=%v\n", config.Ints.Get())
	fmt.Printf("uints=%v\n", config.Uints.Get())
	fmt.Printf("float64s=%v\n", config.Float64s.Get())
	fmt.Printf("strings=%v\n", config.Strings.Get())
	fmt.Printf("durations=%v\n", config.Durations.Get())
	fmt.Printf("intp=%v\n", config.IntP.Get())

	// Output:
	// --- Registered Options ---
	// bool
	// boolt
	// duration
	// durations
	// float64
	// float64s
	// int
	// int32
	// int64
	// intp
	// ints
	// string
	// strings
	// time
	// uint
	// uint32
	// uint64
	// uints
	// --- Before Updating ---
	// bool=false
	// boolt=true
	// int=0
	// int32=0
	// int64=0
	// uint=0
	// uint32=0
	// uint64=0
	// float64=0
	// string=
	// duration=0s
	// time=0001-01-01T00:00:00Z
	// ints=[]
	// uints=[]
	// float64s=[]
	// strings=[]
	// durations=[]
	// intp=123
	// --- After Updating ---
	// bool=true
	// boolt=false
	// int=123
	// int32=123
	// int64=123
	// uint=123
	// uint32=123
	// uint64=123
	// float64=123
	// string=abc
	// duration=10s
	// time=2019-07-27T15:39:34Z
	// ints=[1 2 3]
	// uints=[4 5 6]
	// float64s=[1 2 3]
	// strings=[a b c]
	// durations=[1s 2s 3s]
	// intp=456
}

Documentation

Overview

Package gconf is an extensible and powerful go configuration manager.

Goal

This package is aimed at

  1. A atomic key-value configuration center with the multi-group and the option.
  2. Support the multi-parser to parse the configurations from many sources with the different format.
  3. Change the configuration dynamically during running and watch it.
  4. Observe the change of the configuration.
  5. All of operations are atomic.

Index

Examples

Constants

This section is empty.

Variables

View Source
var (
	// ErrNoOpt is returned when no corresponding option.
	ErrNoOpt = fmt.Errorf("no option")

	// ErrFrozenOpt is returned when to set the value of the option but it's forzen.
	ErrFrozenOpt = fmt.Errorf("option is frozen")
)
View Source
var (
	ToBool     = cast.ToBool     // func(interface{}) (bool, error)
	ToInt      = cast.ToInt      // func(interface{}) (int, error)
	ToInt32    = cast.ToInt32    // func(interface{}) (int32, error)
	ToInt64    = cast.ToInt64    // func(interface{}) (int64, error)
	ToUint     = cast.ToUint     // func(interface{}) (uint, error)
	ToUint32   = cast.ToUint32   // func(interface{}) (uint32, error)
	ToUint64   = cast.ToUint64   // func(interface{}) (uint64, error)
	ToFloat64  = cast.ToFloat64  // func(interface{}) (float64, error)
	ToString   = cast.ToString   // func(interface{}) (string, error)
	ToDuration = cast.ToDuration // func(interface{}) (time.Duration, error)
	ToTime     = toTime          // func(interface{}) (time.Time, error)

	// For string type, it will be split by using cast.ToStringSlice.
	ToIntSlice      = toIntSlice      // func(interface{}) ([]int, error)
	ToUintSlice     = toUintSlice     // func(interface{}) ([]uint, error)
	ToFloat64Slice  = toFloat64Slice  // func(interface{}) ([]float64, error)
	ToStringSlice   = toStringSlice   // func(interface{}) ([]string, error)
	ToDurationSlice = toDurationSlice // func(interface{}) ([]time.Duration, error)
)

Some type converters, all of which have a default implementation, but you can reset them to yourself implementations.

View Source
var (
	AddressOrIPSliceValidator = NewAddressOrIPSliceValidator()
	AddressOrIPValidator      = NewAddressOrIPValidator()
	AddressSliceValidator     = NewAddressSliceValidator()
	AddressValidator          = NewAddressValidator()
	EmailSliceValidator       = NewEmailSliceValidator()
	EmailValidator            = NewEmailValidator()
	EmptyStrValidator         = NewEmptyStrValidator()
	IPSliceValidator          = NewIPSliceValidator()
	IPValidator               = NewIPValidator()
	MaybeAddressOrIPValidator = NewMaybeAddressOrIPValidator()
	MaybeAddressValidator     = NewMaybeAddressValidator()
	MaybeEmailValidator       = NewMaybeEmailValidator()
	MaybeIPValidator          = NewMaybeIPValidator()
	MaybeURLValidator         = NewMaybeURLValidator()
	PortValidator             = NewPortValidator()
	StrNotEmptyValidator      = NewStrNotEmptyValidator()
	URLSliceValidator         = NewURLSliceValidator()
	URLValidator              = NewURLValidator()
)

Predefine some constant validators.

View Source
var Conf = New()

Conf is the default global Config.

The default global Conf will register the option ConfigFileOpt.

View Source
var ConfigFileOpt = StrOpt("config-file", "the config file path.")

ConfigFileOpt is the default option for the configuration file.

View Source
var DefaultWriter = os.Stdout

DefaultWriter is the default writer, which Config will write the information to it by default.

View Source
var VersionOpt = StrOpt("version", "Print the version and exit.").S("v").D("1.0.0").V(NewStrNotEmptyValidator())

VersionOpt reprensents a version option.

Functions

func AddAndParseOptFlag

func AddAndParseOptFlag(c *Config, flagSet ...*flag.FlagSet) error

AddAndParseOptFlag adds the option to the flagSet, which is flag.CommandLine by default, then parses the flagSet.

Notice: if there is the version flag and it is true, it will print the version and exit.

func AddDecoder

func AddDecoder(decoder Decoder, force ...bool) (ok bool)

AddDecoder is equal to Conf.AddDecoder(decoder, force...).

func AddDecoderAlias

func AddDecoderAlias(_type, alias string)

AddDecoderAlias is equal to Conf.AddDecoderAlias(_type, alias).

func AddOptFlag

func AddOptFlag(c *Config, flagSet ...*flag.FlagSet)

AddOptFlag adds the option to the flagSet, which is flag.CommandLine by default.

func Close

func Close()

Close is equal to Conf.Close().

func CloseNotice

func CloseNotice() <-chan struct{}

CloseNotice is equal to Conf.CloseNotice().

func ConvertOptsToCliFlags

func ConvertOptsToCliFlags(group *OptGroup, prefix ...string) []cli.Flag

ConvertOptsToCliFlags converts the options from the group to flags of github.com/urfave/cli/v2.

If prefix is not empty, it will add the prefix to the flag name, and join them with the character "-".

Notice: the character "_" in the flag name will be converted to "-".

func ErrorHandler

func ErrorHandler(h func(err error)) func(error)

ErrorHandler returns a error handler, which will ignore ErrNoOpt and ErrFrozenOpt, and pass the others to h.

func FreezeOpt

func FreezeOpt(names ...string)

FreezeOpt is eqaul to Conf.FreezeOpt(names...).

func Get

func Get(name string) (value interface{})

Get is equal to Conf.Get(name).

func GetBool

func GetBool(name string) bool

GetBool is equal to Conf.GetBool(name).

func GetDuration

func GetDuration(name string) time.Duration

GetDuration is equal to Conf.GetDuration(name).

func GetDurationSlice

func GetDurationSlice(name string) []time.Duration

GetDurationSlice is equal to Conf.GetDurationSlice(name).

func GetFloat64

func GetFloat64(name string) float64

GetFloat64 is equal to Conf.GetFloat64(name).

func GetFloat64Slice

func GetFloat64Slice(name string) []float64

GetFloat64Slice is equal to Conf.GetFloat64Slice(name).

func GetInt

func GetInt(name string) int

GetInt is equal to Conf.GetInt(name).

func GetInt32

func GetInt32(name string) int32

GetInt32 is equal to Conf.GetInt32(name).

func GetInt64

func GetInt64(name string) int64

GetInt64 is equal to Conf.GetInt64(name).

func GetIntSlice

func GetIntSlice(name string) []int

GetIntSlice is equal to Conf.GetIntSlice(name).

func GetString

func GetString(name string) string

GetString is equal to Conf.GetString(name).

func GetStringSlice

func GetStringSlice(name string) []string

GetStringSlice is equal to Conf.GetStringSlice(name).

func GetTime

func GetTime(name string) time.Time

GetTime is equal to Conf.GetTime(name).

func GetUint

func GetUint(name string) uint

GetUint is equal to Conf.GetUint(name).

func GetUint32

func GetUint32(name string) uint32

GetUint32 is equal to Conf.GetUint32(name).

func GetUint64

func GetUint64(name string) uint64

GetUint64 is equal to Conf.GetUint64(name).

func GetUintSlice

func GetUintSlice(name string) []uint

GetUintSlice is equal to Conf.GetUintSlice(name).

func IsErrFrozenOpt

func IsErrFrozenOpt(err error) bool

IsErrFrozenOpt whether reports the error is ErrFrozenOpt or not.

func IsErrNoOpt

func IsErrNoOpt(err error) bool

IsErrNoOpt whether reports the error is ErrNoOpt or not.

func LoadBackupFile

func LoadBackupFile(filename string) error

LoadBackupFile is equal to Conf.LoadBackupFile(filename).

func LoadDataSet

func LoadDataSet(ds DataSet, force ...bool)

LoadDataSet is equal to Conf.LoadDataSet(ds, force...).

func LoadMap

func LoadMap(m map[string]interface{}, force ...bool)

LoadMap is equal to Conf.LoadMap(m, force...).

func LoadSource

func LoadSource(source Source, force ...bool)

LoadSource is equal to Conf.LoadSource(source, force...).

func LoadSourceAndCallback

func LoadSourceAndCallback(source Source, cb func(DataSet), force ...bool)

LoadSourceAndCallback is equal Conf.LoadSourceAndCallback(source, cb, force...).

func LoadSourceAndCallbackWithoutWatch

func LoadSourceAndCallbackWithoutWatch(source Source, cb func(DataSet), force ...bool)

LoadSourceAndCallbackWithoutWatch is equal to Conf.LoadSourceAndCallbackWithoutWatch(source, cb, force...).

func LoadSourceWithoutWatch

func LoadSourceWithoutWatch(source Source, force ...bool)

LoadSourceWithoutWatch is equal to Conf.LoadSourceWithoutWatch(source, force...).

func Must

func Must(name string) (value interface{})

Must is equal to Conf.Must(name).

func MustBool

func MustBool(name string) bool

MustBool is equal to Conf.MustBool(name).

func MustDuration

func MustDuration(name string) time.Duration

MustDuration is equal to Conf.MustDuration(name).

func MustDurationSlice

func MustDurationSlice(name string) []time.Duration

MustDurationSlice is equal to Conf.MustDurationSlice(name).

func MustFloat64

func MustFloat64(name string) float64

MustFloat64 is equal to Conf.MustFloat64(name).

func MustFloat64Slice

func MustFloat64Slice(name string) []float64

MustFloat64Slice is equal to Conf.MustFloat64Slice(name).

func MustInt

func MustInt(name string) int

MustInt is equal to Conf.MustInt(name).

func MustInt32

func MustInt32(name string) int32

MustInt32 is equal to Conf.MustInt32(name).

func MustInt64

func MustInt64(name string) int64

MustInt64 is equal to Conf.MustInt64(name).

func MustIntSlice

func MustIntSlice(name string) []int

MustIntSlice is equal to Conf.MustIntSlice(name).

func MustString

func MustString(name string) string

MustString is equal to Conf.MustString(name).

func MustStringSlice

func MustStringSlice(name string) []string

MustStringSlice is equal to Conf.MustStringSlice(name).

func MustTime

func MustTime(name string) time.Time

MustTime is equal to Conf.MustTime(name).

func MustUint

func MustUint(name string) uint

MustUint is equal to Conf.MustUint(name).

func MustUint32

func MustUint32(name string) uint32

MustUint32 is equal to Conf.MustUint32(name).

func MustUint64

func MustUint64(name string) uint64

MustUint64 is equal to Conf.MustUint64(name).

func MustUintSlice

func MustUintSlice(name string) []uint

MustUintSlice is equal to Conf.MustUintSlice(name).

func Observe

func Observe(observer func(group string, opt string, oldValue, newValue interface{}))

Observe is equal to Conf.Observe(observer).

func ObserveRegister

func ObserveRegister(observer func(group string, opts []Opt))

ObserveRegister is equal to Conf.ObserveRegister(observer).

func OptIsFrozen

func OptIsFrozen(name string) (frozen bool)

OptIsFrozen is equal to Conf.OptIsFrozen(name).

func PrintFlagUsage

func PrintFlagUsage(flagSet *flag.FlagSet)

PrintFlagUsage prints the flag usage instead of the default.

func RegisterOpt

func RegisterOpt(opt Opt, force ...bool) (ok bool)

RegisterOpt is equal to Conf.RegisterOpt(opt, force...).

func RegisterOpts

func RegisterOpts(opts []Opt, force ...bool) (ok bool)

RegisterOpts is equal to Conf.RegisterOpts(opts, force...).

func RegisterStruct

func RegisterStruct(v interface{})

RegisterStruct is equal to Conf.RegisterStruct(v).

func SetErrHandler

func SetErrHandler(handler func(error))

SetErrHandler is equal to Conf.SetErrHandler(handler).

func SetStringVersion

func SetStringVersion(version string)

SetStringVersion is equal to Conf.SetStringVersion(version).

func SetVersion

func SetVersion(version Opt)

SetVersion is equal to Conf.SetVersion(version).

func Snapshot

func Snapshot() map[string]interface{}

Snapshot is equal to Conf.Snapshot().

func Traverse

func Traverse(f func(group string, opt string, value interface{}))

Traverse is equal to Conf.Traverse(f).

func UnfreezeOpt

func UnfreezeOpt(names ...string)

UnfreezeOpt is eqaul to Conf.UnfreezeOpt(names...).

func UpdateOptValue

func UpdateOptValue(groupName, optName string, optValue interface{})

UpdateOptValue is equal to Conf.UpdateOptValue(groupName, optName, optValue).

func UpdateValue

func UpdateValue(key string, value interface{})

UpdateValue is equal to Conf.UpdateValue(key, value).

Types

type BoolOptField

type BoolOptField struct {
	// contains filtered or unexported fields
}

BoolOptField represents the bool option field of the struct.

The default is false.

func (*BoolOptField) Default

func (f *BoolOptField) Default() interface{}

Default implements OptField.Default().

func (*BoolOptField) Get

func (f *BoolOptField) Get() bool

Get returns the value of the option field.

func (*BoolOptField) Parse

func (f *BoolOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*BoolOptField) Set

func (f *BoolOptField) Set(v interface{})

Set implements OptField.Set().

type BoolTOptField

type BoolTOptField struct {
	// contains filtered or unexported fields
}

BoolTOptField represents the bool option field of the struct.

The default is true.

func (*BoolTOptField) Default

func (f *BoolTOptField) Default() interface{}

Default implements OptField.Default().

func (*BoolTOptField) Get

func (f *BoolTOptField) Get() bool

Get returns the value of the option field.

func (*BoolTOptField) Parse

func (f *BoolTOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*BoolTOptField) Set

func (f *BoolTOptField) Set(v interface{})

Set implements OptField.Set().

type Config

type Config struct {
	*OptGroup // The default group.
	// contains filtered or unexported fields
}

Config is used to manage the configuration options.

Example
opts := []Opt{
	BoolOpt("bool", "test bool opt"),
	StrOpt("string", "test string opt"),
	IntOpt("int", "test int opt"),
	Int32Opt("int32", "test int32 opt"),
	Int64Opt("int64", "test int64 opt"),
	UintOpt("uint", "test uint opt"),
	Uint32Opt("uint32", "test uint32 opt"),
	Uint64Opt("uint64", "test uint64 opt"),
	Float64Opt("float64", "test float64 opt"),
	DurationOpt("duration", "test time.Duration opt"),
	TimeOpt("time", "test time.Time opt"),

	// Slice
	IntSliceOpt("ints", "test []int opt"),
	UintSliceOpt("uints", "test []uint opt"),
	Float64SliceOpt("float64s", "test []float64 opt"),
	StrSliceOpt("strings", "test []string opt"),
	DurationSliceOpt("durations", "test []time.Duration opt"),
}

conf := New()
conf.RegisterOpts(opts)

group1 := conf.NewGroup("group1")
group1.RegisterOpts(opts)

group2 := group1.NewGroup("group2") // Or conf.NewGroup("group1.group2")
group2.RegisterOpts(opts)

conf.Set("bool", "1")
conf.Set("string", "abc")
conf.Set("int", "123")
conf.Set("int32", "123")
conf.Set("int64", "123")
conf.Set("uint", "123")
conf.Set("uint32", "123")
conf.Set("uint64", "123")
conf.Set("float64", "123")
conf.Set("duration", "123s")
conf.Set("time", "2019-06-10T18:00:00Z")
conf.Set("ints", "1,2,3")
conf.Set("uints", "1,2,3")
conf.Set("float64s", "1,2,3")
conf.Set("strings", "a,b,c")
conf.Set("durations", "1s,2s,3s")

group1.Set("bool", "1")
group1.Set("string", "efg")
group1.Set("int", "456")
group1.Set("int32", "456")
group1.Set("int64", "456")
group1.Set("uint", "456")
group1.Set("uint32", "456")
group1.Set("uint64", "456")
group1.Set("float64", "456")
group1.Set("duration", "456s")
group1.Set("time", "2019-06-10T19:00:00Z")
group1.Set("ints", "4,5,6")
group1.Set("uints", "4,5,6")
group1.Set("float64s", "4,5,6")
group1.Set("strings", "e,f,g")
group1.Set("durations", "4s,5s,6s")

group2.Set("bool", "1")
group2.Set("string", "xyz")
group2.Set("int", "789")
group2.Set("int32", "789")
group2.Set("int64", "789")
group2.Set("uint", "789")
group2.Set("uint32", "789")
group2.Set("uint64", "789")
group2.Set("float64", "789")
group2.Set("duration", "789s")
group2.Set("time", "2019-06-10T20:00:00Z")
group2.Set("ints", "7,8,9")
group2.Set("uints", "7,8,9")
group2.Set("float64s", "7,8,9")
group2.Set("strings", "x,y,z")
group2.Set("durations", "7s,8s,9s")

////// Output

fmt.Println("[DEFAULT]")
fmt.Println(conf.GetBool("bool"))
fmt.Println(conf.GetInt("int"))
fmt.Println(conf.GetInt32("int32"))
fmt.Println(conf.GetInt64("int64"))
fmt.Println(conf.GetUint("uint"))
fmt.Println(conf.GetUint32("uint32"))
fmt.Println(conf.GetUint64("uint64"))
fmt.Println(conf.GetFloat64("float64"))
fmt.Println(conf.GetString("string"))
fmt.Println(conf.GetDuration("duration"))
fmt.Println(conf.GetTime("time"))
fmt.Println(conf.GetIntSlice("ints"))
fmt.Println(conf.GetUintSlice("uints"))
fmt.Println(conf.GetFloat64Slice("float64s"))
fmt.Println(conf.GetStringSlice("strings"))
fmt.Println(conf.GetDurationSlice("durations"))

fmt.Printf("\n[%s]\n", group1.Name())
fmt.Println(group1.GetBool("bool"))
fmt.Println(group1.GetInt("int"))
fmt.Println(group1.GetInt32("int32"))
fmt.Println(group1.GetInt64("int64"))
fmt.Println(group1.GetUint("uint"))
fmt.Println(group1.GetUint32("uint32"))
fmt.Println(group1.GetUint64("uint64"))
fmt.Println(group1.GetFloat64("float64"))
fmt.Println(group1.GetString("string"))
fmt.Println(group1.GetDuration("duration"))
fmt.Println(group1.GetTime("time"))
fmt.Println(group1.GetIntSlice("ints"))
fmt.Println(group1.GetUintSlice("uints"))
fmt.Println(group1.GetFloat64Slice("float64s"))
fmt.Println(group1.GetStringSlice("strings"))
fmt.Println(group1.GetDurationSlice("durations"))

fmt.Printf("\n[%s]\n", group2.Name())
fmt.Println(group2.GetBool("bool"))
fmt.Println(group2.GetInt("int"))
fmt.Println(group2.GetInt32("int32"))
fmt.Println(group2.GetInt64("int64"))
fmt.Println(group2.GetUint("uint"))
fmt.Println(group2.GetUint32("uint32"))
fmt.Println(group2.GetUint64("uint64"))
fmt.Println(group2.GetFloat64("float64"))
fmt.Println(group2.GetString("string"))
fmt.Println(group2.GetDuration("duration"))
fmt.Println(group2.GetTime("time"))
fmt.Println(group2.GetIntSlice("ints"))
fmt.Println(group2.GetUintSlice("uints"))
fmt.Println(group2.GetFloat64Slice("float64s"))
fmt.Println(group2.GetStringSlice("strings"))
fmt.Println(group2.GetDurationSlice("durations"))
Output:

[DEFAULT]
true
123
123
123
123
123
123
123
abc
2m3s
2019-06-10 18:00:00 +0000 UTC
[1 2 3]
[1 2 3]
[1 2 3]
[a b c]
[1s 2s 3s]

[group1]
true
456
456
456
456
456
456
456
efg
7m36s
2019-06-10 19:00:00 +0000 UTC
[4 5 6]
[4 5 6]
[4 5 6]
[e f g]
[4s 5s 6s]

[group1.group2]
true
789
789
789
789
789
789
789
xyz
13m9s
2019-06-10 20:00:00 +0000 UTC
[7 8 9]
[7 8 9]
[7 8 9]
[x y z]
[7s 8s 9s]

func New

func New() *Config

New returns a new Config.

By default, it will add the "json", "yaml", "toml" and "ini" decoders, and set the aliases of "conf" and "yml" to "ini" and "yaml", for example,

c.AddDecoder(NewJSONDecoder())
c.AddDecoder(NewIniDecoder())
c.AddDecoder(NewYamlDecoder())
c.AddDecoder(NewTomlDecoder())
c.AddDecoderAlias("conf", "ini")
c.AddDecoderAlias("yml", "yaml")

func (*Config) AddDecoder

func (c *Config) AddDecoder(decoder Decoder, force ...bool) (ok bool)

AddDecoder adds a decoder and returns true.

If the decoder has added, it will do nothing and return false. But you can override it by setting force to true.

func (*Config) AddDecoderAlias

func (c *Config) AddDecoderAlias(_type, alias string)

AddDecoderAlias adds the alias of the decoder typed _type. For example,

c.AddDecoderAlias("conf", "ini")

When you get the "conf" decoder and it does not exist, it will try to return the "ini" decoder.

If the alias has existed, it will override it.

func (*Config) AllGroups

func (c *Config) AllGroups() []*OptGroup

AllGroups returns all the groups, containing the default group.

func (*Config) Close

func (c *Config) Close()

Close closes all the watchers and disables anyone to add the watcher into it.

func (*Config) CloseNotice

func (c *Config) CloseNotice() <-chan struct{}

CloseNotice returns a close channel, which will also be closed when the config is closed.

func (*Config) GetDecoder

func (c *Config) GetDecoder(_type string) (decoder Decoder, ok bool)

GetDecoder returns the decoder by the type.

func (*Config) GetVersion

func (c *Config) GetVersion() (version Opt)

GetVersion returns a the version information.

Notice: the Default filed is a string representation of the version value. But it is "" if no version.

func (*Config) LoadBackupFile

func (c *Config) LoadBackupFile(filename string) error

LoadBackupFile loads configuration data from the backup file if exists, then watches the change of the options and write them into the file.

So you can use it as the local cache.

func (*Config) LoadDataSet

func (c *Config) LoadDataSet(ds DataSet, force ...bool)

LoadDataSet loads the DataSet ds, which will parse the data by calling the corresponding decoder and load it.

If a certain option has been set, it will be ignored. But you can set force to true to reset the value of this option.

func (*Config) LoadMap

func (c *Config) LoadMap(m map[string]interface{}, force ...bool)

LoadMap loads the configuration options from the map m.

If a certain option has been set, it will be ignored. But you can set force to true to reset the value of this option.

The map may be the formats as follow:

map[string]interface{} {
    "opt1": "value1",
    "opt2": "value2",
    // ...
    "group1": map[string]interface{} {
        "opt11": "value11",
        "opt12": "value12",
        "group2": map[string]interface{} {
            // ...
        },
        "group3.group4": map[string]interface{} {
            // ...
        }
    },
    "group5.group6.group7": map[string]interface{} {
        "opt71": "value71",
        "opt72": "value72",
        "group8": map[string]interface{} {
            // ...
        },
        "group9.group10": map[string]interface{} {
            // ...
        }
    },
    "group11.group12.opt121": "value121",
    "group11.group12.opt122": "value122"
}

When loading it, it will be flatted to

map[string]interface{} {
    "opt1": "value1",
    "opt2": "value2",
    "group1.opt1": "value11",
    "group1.opt2": "value12",
    "group1.group2.XXX": "XXX",
    "group1.group3.group4.XXX": "XXX",
    "group5.group6.group7.opt71": "value71",
    "group5.group6.group7.opt72": "value72",
    "group5.group6.group7.group8.XXX": "XXX",
    "group5.group6.group7.group9.group10.XXX": "XXX",
    "group11.group12.opt121": "value121",
    "group11.group12.opt122": "value122"
}

So the option name must not contain the dot(.).

func (*Config) LoadSource

func (c *Config) LoadSource(source Source, force ...bool)

LoadSource loads the sources, and call Watch to watch the source.

When loading the source, if a certain option of a certain group has been set, it will be ignored. But you can set force to true to reset the value of this option.

func (*Config) LoadSourceAndCallback

func (c *Config) LoadSourceAndCallback(source Source, cb func(DataSet), force ...bool)

LoadSourceAndCallback is the same as LoadSource, but set the callback of the Dataset to cb.

func (*Config) LoadSourceAndCallbackWithoutWatch

func (c *Config) LoadSourceAndCallbackWithoutWatch(source Source, cb func(DataSet), force ...bool)

LoadSourceAndCallbackWithoutWatch is the same as LoadSourceWithoutWatch, but set the callback of the Dataset to cb.

func (*Config) LoadSourceWithoutWatch

func (c *Config) LoadSourceWithoutWatch(source Source, force ...bool)

LoadSourceWithoutWatch is the same as LoadSource, but does not call the Watch method of the source to watch the source.

func (*Config) Observe

func (c *Config) Observe(observer func(group string, opt string, oldValue, newValue interface{}))

Observe appends the observer to watch the change of all the option value.

Example
conf := New()
conf.RegisterOpt(StrOpt("opt1", "").D("abc"))
conf.NewGroup("group").RegisterOpt(IntOpt("opt2", "").D(123))
conf.Observe(func(group, opt string, old, new interface{}) {
	fmt.Printf("Setting: group=%s, opt=%s, old=%v, new=%v\n", group, opt, old, new)
})

conf.Set("opt1", "xyz")
conf.Group("group").Set("opt2", 789)
Output:

Setting: group=, opt=opt1, old=abc, new=xyz
Setting: group=group, opt=opt2, old=123, new=789

func (*Config) ObserveRegister

func (c *Config) ObserveRegister(observer func(group string, opts []Opt))

ObserveRegister appends the observer to watch the register of the option.

Example
conf := New()
conf.ObserveRegister(func(group string, opts []Opt) {
	for _, opt := range opts {
		fmt.Printf("Register Opt: group=%s, opt=%s\n", group, opt.Name)
	}
})

conf.RegisterOpt(StrOpt("opt1", "").D("abc"))
conf.NewGroup("group").RegisterOpt(IntOpt("opt2", "").D(123))
Output:

Register Opt: group=, opt=opt1
Register Opt: group=group, opt=opt2

func (*Config) PrintGroup

func (c *Config) PrintGroup(w io.Writer) error

PrintGroup prints the information of all groups to w.

func (*Config) SetErrHandler

func (c *Config) SetErrHandler(h func(error))

SetErrHandler resets the error handler to h.

The default is output to DefaultWriter, but it ignores ErrNoOpt and ErrFrozenOpt.

Example
conf := New()
conf.RegisterOpt(StrOpt("opt1", "").D("abc").V(NewStrLenValidator(0, 6)))
conf.NewGroup("group").RegisterOpt(IntOpt("opt2", "").D(123).V(NewIntegerRangeValidator(100, 200)))
conf.SetErrHandler(func(err error) { fmt.Println(err) })

conf.Set("opt1", "abcdefg")
conf.Group("group").Set("opt2", 300)
Output:

[Config] invalid setting for 'opt1': the length of 'abcdefg' is 7, not between 0 and 6
[Config] invalid setting for 'group:opt2': the value '300' is not between 100 and 200

func (*Config) SetStringVersion

func (c *Config) SetStringVersion(version string)

SetStringVersion is equal to c.SetVersion(VersionOpt.D(version)).

func (*Config) SetVersion

func (c *Config) SetVersion(version Opt)

SetVersion sets the version information.

Notice: the field Default must be a string.

func (*Config) Snapshot

func (c *Config) Snapshot() map[string]interface{}

Snapshot returns the snapshot of the whole configuration options.

Notice: the key includes the group name and the option name, for instance,

map[string]interface{} {
    "opt1": "value1",
    "opt2": "value2",
    "group1.opt3": "value3",
    "group1.group2.opt4": "value4",
    // ...
}
Example
conf := New()
conf.RegisterOpt(StrOpt("opt1", ""))
conf.NewGroup("group1").RegisterOpt(IntOpt("opt2", ""))
conf.NewGroup("group1").NewGroup("group2").RegisterOpt(IntOpt("opt3", ""))

// For test
print := func(snap map[string]interface{}) {
	data, _ := json.Marshal(conf.Snapshot())
	fmt.Println(string(data))
}

print(conf.Snapshot())

conf.Set("opt1", "abc")
print(conf.Snapshot())

conf.Group("group1").Set("opt2", 123)
print(conf.Snapshot())

conf.Group("group1.group2").Set("opt3", 456)
print(conf.Snapshot())
Output:

{"group1.group2.opt3":0,"group1.opt2":0,"opt1":""}
{"group1.group2.opt3":0,"group1.opt2":0,"opt1":"abc"}
{"group1.group2.opt3":0,"group1.opt2":123,"opt1":"abc"}
{"group1.group2.opt3":456,"group1.opt2":123,"opt1":"abc"}

func (*Config) Traverse

func (c *Config) Traverse(f func(group string, opt string, value interface{}))

Traverse traverses all the options of all the groups.

Example
conf := New()
conf.RegisterOpt(StrOpt("opt1", "").D("abc"))
conf.NewGroup("group1").RegisterOpt(IntOpt("opt2", "").D(123))
conf.NewGroup("group1").NewGroup("group2").RegisterOpt(IntOpt("opt3", "").D(456))

conf.Traverse(func(group, opt string, value interface{}) {
	fmt.Printf("group=%s, opt=%s, value=%v\n", group, opt, value)
})
Output:

group=, opt=opt1, value=abc
group=group1, opt=opt2, value=123
group=group1.group2, opt=opt3, value=456

func (*Config) UpdateOptValue

func (c *Config) UpdateOptValue(groupName, optName string, optValue interface{})

UpdateOptValue updates the value of the option of the group.

If the group or the option does not exist, it will be ignored.

func (*Config) UpdateValue

func (c *Config) UpdateValue(key string, value interface{})

UpdateValue is the same as UpdateOptValue, but key is equal to `fmt.Sprintf("%s.%s", groupName, optName)`.

that's,

c.UpdateOptValue(groupName, optName, optValue)

is equal to

c.UpdateValue(fmt.Sprintf("%s.%s", groupName, optName), optValue)

type DataSet

type DataSet struct {
	Data      []byte    // The original data.
	Format    string    // Such as "json", "xml", etc.
	Source    string    // Such as "file:/path/to/file", "zk:127.0.0.1:2181", etc.
	Checksum  string    // Such as "md5:7d2f31e6fff478337478413ee1b70d2a", etc.
	Timestamp time.Time // The timestamp when the data is modified.

	// Callback will be called after loading the dataset, if it exists.
	Callback func(DataSet)
}

DataSet represents the information of the configuration data.

func (DataSet) Md5

func (ds DataSet) Md5() string

Md5 returns the md5 checksum of the DataSet data

func (DataSet) Sha256

func (ds DataSet) Sha256() string

Sha256 returns the sha256 checksum of the DataSet data

type Decoder

type Decoder struct {
	// Type is the type of decoder, such as "json", "xml", which is case insensitive.
	Type string

	// Decode is used to decode the configuration data.
	//
	// The decoder maybe decode the src data to the formats as follow:
	//
	//     map[string]interface{} {
	//         "opt1": "value1",
	//         "opt2": "value2",
	//         // ...
	//         "group1": map[string]interface{} {
	//             "opt11": "value11",
	//             "opt12": "value12",
	//             "group2": map[string]interface{} {
	//                 // ...
	//             },
	//             "group3.group4": map[string]interface{} {
	//                 // ...
	//             }
	//         },
	//         "group5.group6.group7": map[string]interface{} {
	//             "opt71": "value71",
	//             "opt72": "value72",
	//             "group8": map[string]interface{} {
	//                 // ...
	//             },
	//             "group9.group10": map[string]interface{} {
	//                 // ...
	//             }
	//         },
	//         "group11.group12.opt121": "value121",
	//         "group11.group12.opt122": "value122"
	//     }
	//
	// When loading it, it will be flatted to
	//
	//     map[string]interface{} {
	//         "opt1": "value1",
	//         "opt2": "value2",
	//         "group1.opt1": "value11",
	//         "group1.opt2": "value12",
	//         "group1.group2.XXX": "XXX",
	//         "group1.group3.group4.XXX": "XXX",
	//         "group5.group6.group7.opt71": "value71",
	//         "group5.group6.group7.opt72": "value72",
	//         "group5.group6.group7.group8.XXX": "XXX",
	//         "group5.group6.group7.group9.group10.XXX": "XXX",
	//         "group11.group12.opt121": "value121",
	//         "group11.group12.opt122": "value122"
	//     }
	//
	// So the option name must not contain the dot(.).
	Decode func(src []byte, dst map[string]interface{}) error
}

Decoder is used to decode the configuration data.

func GetDecoder

func GetDecoder(_type string) (decoder Decoder, ok bool)

GetDecoder is equal to Conf.GetDecoder(_type).

func NewDecoder

func NewDecoder(_type string, decode func([]byte, map[string]interface{}) error) Decoder

NewDecoder returns a new decoder.

func NewIniDecoder

func NewIniDecoder(defaultGroupName ...string) Decoder

NewIniDecoder returns a INI decoder to decode the INI data.

Notice:

  1. The empty line will be ignored.
  2. The spacewhite on the beginning and end of line or value will be trimmed.
  3. The comment line starts with the character '#' or ';', which is ignored.
  4. The name of the default group is "DEFAULT", but it is optional.
  5. The group can nest other groups by ".", such as "group1.group2.group3".
  6. The key must only contain the printable non-spacewhite characters.
  7. The line can continue to the next line with the last character "\", and the spacewhite on the beginning and end of the each line will be trimmed, then combines them with a space.

func NewJSONDecoder

func NewJSONDecoder() Decoder

NewJSONDecoder returns a json decoder to decode the json data.

If the json data contains the comment line starting with "//", it will remove the comment line and parse the json data.

Example
data := []byte(`{
		// user name
		"name": "Aaron",
		"age": 123,

		// the other information
		"other": {
			// address
			"home": "http://www.example.com"
		}
	}`)

ms := make(map[string]interface{})
err := NewJSONDecoder().Decode(data, ms)

fmt.Println(err)
fmt.Println(len(ms))
fmt.Println(ms["name"])
fmt.Println(ms["age"])
fmt.Println(ms["other"])
Output:

<nil>
3
Aaron
123
map[home:http://www.example.com]

func NewTomlDecoder

func NewTomlDecoder() Decoder

NewTomlDecoder returns a toml decoder to decode the toml data.

func NewYamlDecoder

func NewYamlDecoder() Decoder

NewYamlDecoder returns a yaml decoder to decode the yaml data.

type DurationOptField

type DurationOptField struct {
	// contains filtered or unexported fields
}

DurationOptField represents the time.Duration option field of the struct.

func (*DurationOptField) Default

func (f *DurationOptField) Default() interface{}

Default implements OptField.Default().

func (*DurationOptField) Get

func (f *DurationOptField) Get() time.Duration

Get returns the value of the option field.

func (*DurationOptField) Parse

func (f *DurationOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*DurationOptField) Set

func (f *DurationOptField) Set(v interface{})

Set implements OptField.Set().

type DurationSliceOptField

type DurationSliceOptField struct {
	// contains filtered or unexported fields
}

DurationSliceOptField represents the []time.Duration option field of the struct.

func (*DurationSliceOptField) Default

func (f *DurationSliceOptField) Default() interface{}

Default implements OptField.Default().

func (*DurationSliceOptField) Get

func (f *DurationSliceOptField) Get() []time.Duration

Get returns the value of the option field.

func (*DurationSliceOptField) Parse

func (f *DurationSliceOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*DurationSliceOptField) Set

func (f *DurationSliceOptField) Set(v interface{})

Set implements OptField.Set().

type Float64OptField

type Float64OptField struct {
	// contains filtered or unexported fields
}

Float64OptField represents the float64 option field of the struct.

func (*Float64OptField) Default

func (f *Float64OptField) Default() interface{}

Default implements OptField.Default().

func (*Float64OptField) Get

func (f *Float64OptField) Get() float64

Get returns the value of the option field.

func (*Float64OptField) Parse

func (f *Float64OptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*Float64OptField) Set

func (f *Float64OptField) Set(v interface{})

Set implements OptField.Set().

type Float64SliceOptField

type Float64SliceOptField struct {
	// contains filtered or unexported fields
}

Float64SliceOptField represents the []float64 option field of the struct.

func (*Float64SliceOptField) Default

func (f *Float64SliceOptField) Default() interface{}

Default implements OptField.Default().

func (*Float64SliceOptField) Get

func (f *Float64SliceOptField) Get() []float64

Get returns the value of the option field.

func (*Float64SliceOptField) Parse

func (f *Float64SliceOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*Float64SliceOptField) Set

func (f *Float64SliceOptField) Set(v interface{})

Set implements OptField.Set().

type Int32OptField

type Int32OptField struct {
	// contains filtered or unexported fields
}

Int32OptField represents the int32 option field of the struct.

func (*Int32OptField) Default

func (f *Int32OptField) Default() interface{}

Default implements OptField.Default().

func (*Int32OptField) Get

func (f *Int32OptField) Get() int32

Get returns the value of the option field.

func (*Int32OptField) Parse

func (f *Int32OptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*Int32OptField) Set

func (f *Int32OptField) Set(v interface{})

Set implements OptField.Set().

type Int64OptField

type Int64OptField struct {
	// contains filtered or unexported fields
}

Int64OptField represents the int64 option field of the struct.

func (*Int64OptField) Default

func (f *Int64OptField) Default() interface{}

Default implements OptField.Default().

func (*Int64OptField) Get

func (f *Int64OptField) Get() int64

Get returns the value of the option field.

func (*Int64OptField) Parse

func (f *Int64OptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*Int64OptField) Set

func (f *Int64OptField) Set(v interface{})

Set implements OptField.Set().

type IntOptField

type IntOptField struct {
	// contains filtered or unexported fields
}

IntOptField represents the int option field of the struct.

func (*IntOptField) Default

func (f *IntOptField) Default() interface{}

Default implements OptField.Default().

func (*IntOptField) Get

func (f *IntOptField) Get() int

Get returns the value of the option field.

func (*IntOptField) Parse

func (f *IntOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*IntOptField) Set

func (f *IntOptField) Set(v interface{})

Set implements OptField.Set().

type IntSliceOptField

type IntSliceOptField struct {
	// contains filtered or unexported fields
}

IntSliceOptField represents the []int option field of the struct.

func (*IntSliceOptField) Default

func (f *IntSliceOptField) Default() interface{}

Default implements OptField.Default().

func (*IntSliceOptField) Get

func (f *IntSliceOptField) Get() []int

Get returns the value of the option field.

func (*IntSliceOptField) Parse

func (f *IntSliceOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*IntSliceOptField) Set

func (f *IntSliceOptField) Set(v interface{})

Set implements OptField.Set().

type Opt

type Opt struct {
	// Name is the long name of the option.
	// It's necessary and must not be empty.
	Name string

	// Short is the short name of the option, which is optional.
	//
	// It should be a single-character string, such as "v" for "version".
	Short string

	// Help is the help or usage information, which is optional.
	Help string

	// Cli indicates whether the option can be used for the CLI flag.
	Cli bool

	// Tags is the key-value metadata of the Opt.
	Tags map[string]string

	// The list of the aliases of the option, which will be registered to
	// the group that the option is registered when it is being registered.
	Aliases []string

	// Default is the default value of the option, which is necessary
	// and must not be nil. It will be used to indicate the type of the option.
	Default interface{}

	// Parser is used to parse the input option value to a specific type,
	// Which is necessary.
	//
	// Notice: it must not panic.
	Parser func(input interface{}) (output interface{}, err error)

	// Fix is used to fix the parsed value.
	//
	// The different between Parser and Fix:
	//   1. Parser only parses the value from the arbitrary type to a specific.
	//   2. Fix only changes the value, not the type, that's, input and output
	//      should be the same type. For example, input is the NIC name,
	//      and Fix can get the ip by the NIC name then return it as output.
	//      So it ensures that input may be NIC or IP, and that the value
	//      of the option is always a IP.
	Fix func(input interface{}) (output interface{}, err error)

	// Observers are called after the value of the option is updated.
	Observers []func(newValue interface{})

	// Validators is the validators of the option, which is optional.
	//
	// When updating the option value, the validators will validate it.
	// If there is a validator returns an error, the updating fails and
	// returns the error. That's, these validators are the AND relations.
	//
	// Notice: they must not panic.
	Validators []Validator
	// contains filtered or unexported fields
}

Opt is used to represent a option vlaue.

func BoolOpt

func BoolOpt(name string, help string) Opt

BoolOpt returns a bool Opt, which is equal to

NewOpt(name, false, ToBool).H(help)

func DurationOpt

func DurationOpt(name string, help string) Opt

DurationOpt returns a time.Duration Opt, which is equal to

NewOpt(name, time.Duration(0), ToDuration).H(help)

func DurationSliceOpt

func DurationSliceOpt(name string, help string) Opt

DurationSliceOpt returns a []time.Duration Opt, which is equal to

NewOpt(name, []time.Duration{}, ToDurationSlice).H(help)

func Float64Opt

func Float64Opt(name string, help string) Opt

Float64Opt returns a float64 Opt, which is equal to

NewOpt(name, 0.0, ToFloat64).H(help)

func Float64SliceOpt

func Float64SliceOpt(name string, help string) Opt

Float64SliceOpt returns a []float64 Opt, which is equal to

NewOpt(name, []float64{}, ToFloat64Slice).H(help)

func GetVersion

func GetVersion() Opt

GetVersion is equal to Conf.GetVersion().

func Int32Opt

func Int32Opt(name string, help string) Opt

Int32Opt returns a int32 Opt, which is equal to

NewOpt(name, int32(0), ToInt32).H(help)

func Int64Opt

func Int64Opt(name string, help string) Opt

Int64Opt returns a int64 Opt, which is equal to

NewOpt(name, int64(0), ToInt64).H(help)

func IntOpt

func IntOpt(name string, help string) Opt

IntOpt returns a int Opt, which is equal to

NewOpt(name, 0, ToInt).H(help)

func IntSliceOpt

func IntSliceOpt(name string, help string) Opt

IntSliceOpt returns a []int Opt, which is equal to

NewOpt(name, []int{}, ToIntSlice).H(help)

func NewOpt

func NewOpt(name string, _default interface{}, parser func(interface{}) (interface{}, error)) Opt

NewOpt returns a new Opt.

Notice: Cli is true by default.

func StrOpt

func StrOpt(name string, help string) Opt

StrOpt returns a string Opt, which is equal to

NewOpt(name, "", ToString).H(help)

func StrSliceOpt

func StrSliceOpt(name string, help string) Opt

StrSliceOpt returns a []string Opt, which is equal to

NewOpt(name, []string{}, ToStringSlice).H(help)

func TimeOpt

func TimeOpt(name string, help string) Opt

TimeOpt returns a time.Time Opt, which is equal to

NewOpt(name, time.Time{}, ToTime).H(help)

func Uint32Opt

func Uint32Opt(name string, help string) Opt

Uint32Opt returns a uint32 Opt, which is equal to

NewOpt(name, uint32(0), ToUint32).H(help)

func Uint64Opt

func Uint64Opt(name string, help string) Opt

Uint64Opt returns a uint64 Opt, which is equal to

NewOpt(name, uint64(0), ToUint64).H(help)

func UintOpt

func UintOpt(name string, help string) Opt

UintOpt returns a uint Opt, which is equal to

NewOpt(name, uint(0), ToUint).H(help)

func UintSliceOpt

func UintSliceOpt(name string, help string) Opt

UintSliceOpt returns a []uint Opt, which is equal to

NewOpt(name, []uint{}, ToUintSlice).H(help)

func (Opt) As

func (o Opt) As(aliases ...string) Opt

As returns a new Opt with the new aliases based on the current option, which will append them.

func (Opt) C

func (o Opt) C(cli bool) Opt

C returns a new Opt with the cli flag based on the current option.

func (Opt) D

func (o Opt) D(_default interface{}) Opt

D returns a new Opt with the given default value based on the current option.

func (Opt) F added in v4.2.0

func (o Opt) F(fix func(interface{}) (interface{}, error), fixDefault ...bool) Opt

F returns a new Opt with the given fix function based on the current option.

If fixDefault is true, it will fix the default value when registering the option.

Example
fix := func(v interface{}) (interface{}, error) { return v.(int) + 1, nil }
opt1 := IntOpt("opt1", "test fix with default").D(10).F(fix, true)
opt2 := IntOpt("opt2", "test fix without default").D(20).F(fix)

conf := New()
conf.RegisterOpts([]Opt{opt1, opt2})

fmt.Printf("opt1=%s\n", conf.MustString("opt1"))
fmt.Printf("opt2=%s\n", conf.MustString("opt2"))

conf.UpdateValue("opt1", 30)
conf.UpdateValue("opt2", 40)

fmt.Printf("opt1=%s\n", conf.MustString("opt1"))
fmt.Printf("opt2=%s\n", conf.MustString("opt2"))
Output:

opt1=11
opt2=20
opt1=31
opt2=41

func (Opt) H

func (o Opt) H(help string) Opt

H returns a new Opt with the given help based on the current option.

func (Opt) N

func (o Opt) N(name string) Opt

N returns a new Opt with the given name based on the current option.

func (Opt) O

func (o Opt) O(observers ...func(interface{})) Opt

O returns a new Opt with the given observer based on the current option, which will append them.

func (Opt) P

func (o Opt) P(parser func(interface{}) (interface{}, error)) Opt

P returns a new Opt with the given parser based on the current option.

func (Opt) S

func (o Opt) S(shortName string) Opt

S returns a new Opt with the given short name based on the current option.

func (Opt) T

func (o Opt) T(key, value string) Opt

T returns a new Opt with the key-value tag based on the current option, which will clone the tags from the current option to the new.

Notice: the key must not be empty, but value may be.

func (Opt) V

func (o Opt) V(validators ...Validator) Opt

V returns a new Opt with the given validators based on the current option, which will append them.

type OptError

type OptError struct {
	Group string
	Opt   string
	Err   error
	Value interface{}
}

OptError is used to represent an error about option.

func NewOptError

func NewOptError(group, opt string, err error, value interface{}) OptError

NewOptError returns a new OptError.

func (OptError) Error

func (e OptError) Error() string

type OptField

type OptField interface {
	// Default returns the default value of the field option.
	Default() interface{}

	// Parse converts the input to output.
	//
	// Notice: the type of output must be identical with the types of the value
	// returned by Default() and the argument of Set().
	Parse(input interface{}) (output interface{}, err error)

	// Set is used to update the value of the field, which must be goroutine-safe.
	Set(interface{})
}

OptField is used to describe a struct field option, which can get or set the value of the struct field safely.

Example
type AppConfig struct {
	Bool      BoolOptField
	BoolT     BoolTOptField
	Int       IntOptField
	Int32     Int32OptField
	Int64     Int64OptField
	Uint      UintOptField
	Uint32    Uint32OptField
	Uint64    Uint64OptField
	Float64   Float64OptField
	String    StringOptField
	Duration  DurationOptField
	Time      TimeOptField
	Ints      IntSliceOptField
	Uints     UintSliceOptField
	Float64s  Float64SliceOptField
	Strings   StringSliceOptField
	Durations DurationSliceOptField

	// Pointer Example
	IntP   *IntOptField `default:"123"`
	Ignore *StringOptField
}

// Notice: for the pointer to the option field, it must be initialized.
// Or it will be ignored.
config := AppConfig{IntP: &IntOptField{}}
conf := New()
conf.RegisterStruct(&config)

fmt.Println("--- Registered Options ---")
for _, opt := range conf.AllOpts() {
	fmt.Println(opt.Name)
}

fmt.Println("--- Before Updating ---")
fmt.Printf("bool=%v\n", config.Bool.Get())
fmt.Printf("boolt=%v\n", config.BoolT.Get())
fmt.Printf("int=%v\n", config.Int.Get())
fmt.Printf("int32=%v\n", config.Int32.Get())
fmt.Printf("int64=%v\n", config.Int64.Get())
fmt.Printf("uint=%v\n", config.Uint.Get())
fmt.Printf("uint32=%v\n", config.Uint32.Get())
fmt.Printf("uint64=%v\n", config.Uint64.Get())
fmt.Printf("float64=%v\n", config.Float64.Get())
fmt.Printf("string=%v\n", config.String.Get())
fmt.Printf("duration=%v\n", config.Duration.Get())
fmt.Printf("time=%v\n", config.Time.Get().Format(time.RFC3339))
fmt.Printf("ints=%v\n", config.Ints.Get())
fmt.Printf("uints=%v\n", config.Uints.Get())
fmt.Printf("float64s=%v\n", config.Float64s.Get())
fmt.Printf("strings=%v\n", config.Strings.Get())
fmt.Printf("durations=%v\n", config.Durations.Get())
fmt.Printf("intp=%v\n", config.IntP.Get())

conf.Set("bool", true)
conf.Set("boolt", false)
conf.Set("int", 123)
conf.Set("int32", 123)
conf.Set("int64", 123)
conf.Set("uint", 123)
conf.Set("uint32", 123)
conf.Set("uint64", 123)
conf.Set("float64", 123)
conf.Set("string", "abc")
conf.Set("duration", "10s")
conf.Set("time", "2019-07-27 15:39:34")
conf.Set("ints", []int{1, 2, 3})
conf.Set("uints", []uint{4, 5, 6})
conf.Set("float64s", []float64{1, 2, 3})
conf.Set("strings", []string{"a", "b", "c"})
conf.Set("durations", []time.Duration{time.Second, time.Second * 2, time.Second * 3})
conf.Set("intp", 456)

fmt.Println("--- After Updating ---")
fmt.Printf("bool=%v\n", config.Bool.Get())
fmt.Printf("boolt=%v\n", config.BoolT.Get())
fmt.Printf("int=%v\n", config.Int.Get())
fmt.Printf("int32=%v\n", config.Int32.Get())
fmt.Printf("int64=%v\n", config.Int64.Get())
fmt.Printf("uint=%v\n", config.Uint.Get())
fmt.Printf("uint32=%v\n", config.Uint32.Get())
fmt.Printf("uint64=%v\n", config.Uint64.Get())
fmt.Printf("float64=%v\n", config.Float64.Get())
fmt.Printf("string=%v\n", config.String.Get())
fmt.Printf("duration=%v\n", config.Duration.Get())
fmt.Printf("time=%v\n", config.Time.Get().Format(time.RFC3339))
fmt.Printf("ints=%v\n", config.Ints.Get())
fmt.Printf("uints=%v\n", config.Uints.Get())
fmt.Printf("float64s=%v\n", config.Float64s.Get())
fmt.Printf("strings=%v\n", config.Strings.Get())
fmt.Printf("durations=%v\n", config.Durations.Get())
fmt.Printf("intp=%v\n", config.IntP.Get())
Output:

--- Registered Options ---
bool
boolt
duration
durations
float64
float64s
int
int32
int64
intp
ints
string
strings
time
uint
uint32
uint64
uints
--- Before Updating ---
bool=false
boolt=true
int=0
int32=0
int64=0
uint=0
uint32=0
uint64=0
float64=0
string=
duration=0s
time=0001-01-01T00:00:00Z
ints=[]
uints=[]
float64s=[]
strings=[]
durations=[]
intp=123
--- After Updating ---
bool=true
boolt=false
int=123
int32=123
int64=123
uint=123
uint32=123
uint64=123
float64=123
string=abc
duration=10s
time=2019-07-27T15:39:34Z
ints=[1 2 3]
uints=[4 5 6]
float64s=[1 2 3]
strings=[a b c]
durations=[1s 2s 3s]
intp=456

type OptGroup

type OptGroup struct {
	// contains filtered or unexported fields
}

OptGroup is the group of the options.

func AllGroups

func AllGroups() []*OptGroup

AllGroups is equal to Conf.AllGroups().

func G

func G(group string) *OptGroup

G is short for Group.

func Group

func Group(group string) *OptGroup

Group is equal to Conf.Group(group).

func MustG

func MustG(group string) *OptGroup

MustG is short for MustGroup(group).

func MustGroup

func MustGroup(group string) *OptGroup

MustGroup is equal to Conf.MustGroup(group).

func NewGroup

func NewGroup(group string) *OptGroup

NewGroup is eqaul to Conf.NewGroup(group).

func (*OptGroup) AllOpts

func (g *OptGroup) AllOpts() []Opt

AllOpts returns all the options in the current group.

func (*OptGroup) Config

func (g *OptGroup) Config() *Config

Config returns the Config that the current group belongs to.

func (*OptGroup) FreezeGroup

func (g *OptGroup) FreezeGroup()

FreezeGroup freezes the current group and disable its options to be set.

If the current group has been frozen, it does nothing.

func (*OptGroup) FreezeOpt

func (g *OptGroup) FreezeOpt(names ...string)

FreezeOpt freezes these options and disable them to be set.

If the option does not exist has been frozen, it does nothing for it.

Example
conf := New()
conf.NewGroup("group1").RegisterOpts([]Opt{StrOpt("opt1", "").D("a"), StrOpt("opt2", "").D("b")})
conf.NewGroup("group2").RegisterOpts([]Opt{StrOpt("opt3", "").D("c"), StrOpt("opt4", "").D("d")})
conf.Group("group1").FreezeOpt("opt2")
conf.Group("group2").FreezeGroup()

errs := make([]error, 0, 4)
conf.SetErrHandler(func(err error) { errs = append(errs, err) })

conf.UpdateValue("group1.opt1", "o")
conf.UpdateOptValue("group1", "opt2", "p")
conf.UpdateOptValue("group2", "opt3", "q")
conf.UpdateOptValue("group2", "opt4", "r")

fmt.Println(len(errs))
fmt.Println(conf.Group("group1").GetString("opt1"))
fmt.Println(conf.Group("group1").GetString("opt2"))
fmt.Println(conf.Group("group2").GetString("opt3"))
fmt.Println(conf.Group("group2").GetString("opt4"))
Output:

3
o
b
c
d

func (*OptGroup) G

func (g *OptGroup) G(group string) *OptGroup

G is the alias of Group.

func (*OptGroup) Get

func (g *OptGroup) Get(name string) (value interface{})

Get returns the value of the option named name.

Return nil if this option does not exist.

func (*OptGroup) GetBool

func (g *OptGroup) GetBool(name string) bool

GetBool is the same as Get(name), but returns the bool value.

func (*OptGroup) GetDuration

func (g *OptGroup) GetDuration(name string) time.Duration

GetDuration is the same as Get(name), but returns the time.Duration value.

func (*OptGroup) GetDurationSlice

func (g *OptGroup) GetDurationSlice(name string) []time.Duration

GetDurationSlice is the same as Get(name), but returns the []time.Duration value.

func (*OptGroup) GetFloat64

func (g *OptGroup) GetFloat64(name string) float64

GetFloat64 is the same as Get(name), but returns the float64 value.

func (*OptGroup) GetFloat64Slice

func (g *OptGroup) GetFloat64Slice(name string) []float64

GetFloat64Slice is the same as Get(name), but returns the []float64 value.

func (*OptGroup) GetInt

func (g *OptGroup) GetInt(name string) int

GetInt is the same as Get(name), but returns the int value.

func (*OptGroup) GetInt32

func (g *OptGroup) GetInt32(name string) int32

GetInt32 is the same as Get(name), but returns the int32 value.

func (*OptGroup) GetInt64

func (g *OptGroup) GetInt64(name string) int64

GetInt64 is the same as Get(name), but returns the int64 value.

func (*OptGroup) GetIntSlice

func (g *OptGroup) GetIntSlice(name string) []int

GetIntSlice is the same as Get(name), but returns the []int value.

func (*OptGroup) GetString

func (g *OptGroup) GetString(name string) string

GetString is the same as Get(name), but returns the string value.

func (*OptGroup) GetStringSlice

func (g *OptGroup) GetStringSlice(name string) []string

GetStringSlice is the same as Get(name), but returns the []string value.

func (*OptGroup) GetTime

func (g *OptGroup) GetTime(name string) time.Time

GetTime is the same as Get(name), but returns the time.Time value.

func (*OptGroup) GetUint

func (g *OptGroup) GetUint(name string) uint

GetUint is the same as Get(name), but returns the uint value.

func (*OptGroup) GetUint32

func (g *OptGroup) GetUint32(name string) uint32

GetUint32 is the same as Get(name), but returns the uint32 value.

func (*OptGroup) GetUint64

func (g *OptGroup) GetUint64(name string) uint64

GetUint64 is the same as Get(name), but returns the uint64 value.

func (*OptGroup) GetUintSlice

func (g *OptGroup) GetUintSlice(name string) []uint

GetUintSlice is the same as Get(name), but returns the []uint value.

func (*OptGroup) Group

func (g *OptGroup) Group(group string) *OptGroup

Group returns the sub-group named group.

It supports the cascaded group name, for example, the following ways are equal.

g.Group("group1.group2.group3")
g.Group("group1").Group("group2.group3")
g.Group("group1.group2").Group("group3")
g.Group("group1").Group("group2").Group("group3")

Notice: if the group is "", it will return the current group.

func (*OptGroup) GroupIsFrozen

func (g *OptGroup) GroupIsFrozen() (frozen bool)

GroupIsFrozen reports whether the current group named name is frozen.

func (*OptGroup) HasOpt

func (g *OptGroup) HasOpt(name string) bool

HasOpt reports whether there is an option named name in the current group.

func (*OptGroup) HasOptAndIsNotSet

func (g *OptGroup) HasOptAndIsNotSet(name string) (yes bool)

HasOptAndIsNotSet reports whether the option named name exists and hasn't been set, which is equal to `g.HasOpt(name) && !g.OptIsSet(name)`.

func (*OptGroup) Migrate added in v4.1.0

func (g *OptGroup) Migrate(oldOptName, newGroupOptName string)

Migrate migrates the old option oldOptName to the other option of the other group, newGroupOptName, which will update the value of newGroupOptName to the new when the value of oldOptName is updated.

Example
conf := New()
conf.RegisterOpt(StrOpt("opt1", "").D("abc"))
conf.RegisterOpt(StrOpt("opt2", "").D("efg"))
conf.NewGroup("group1").RegisterOpt(StrOpt("opt3", "").D("opq"))
conf.NewGroup("group1").RegisterOpt(StrOpt("opt4", "").D("rst"))

conf.Migrate("opt1", "group1.opt3")
conf.Group("group1").Migrate("opt4", "opt2")

fmt.Printf("--- Before Updating ---\n")
fmt.Printf("opt1=%v\n", conf.MustString("opt1"))
fmt.Printf("opt2=%v\n", conf.MustString("opt2"))
fmt.Printf("group1.opt3=%v\n", conf.G("group1").MustString("opt3"))
fmt.Printf("group1.opt4=%v\n", conf.G("group1").MustString("opt4"))

conf.UpdateValue("opt1", "uvw")
conf.UpdateValue("group1.opt4", "xyz")

fmt.Printf("--- After Updating ---\n")
fmt.Printf("opt1=%v\n", conf.MustString("opt1"))
fmt.Printf("opt2=%v\n", conf.MustString("opt2"))
fmt.Printf("group1.opt3=%v\n", conf.G("group1").MustString("opt3"))
fmt.Printf("group1.opt4=%v\n", conf.G("group1").MustString("opt4"))
Output:

--- Before Updating ---
opt1=abc
opt2=efg
group1.opt3=opq
group1.opt4=rst
--- After Updating ---
opt1=uvw
opt2=xyz
group1.opt3=uvw
group1.opt4=xyz

func (*OptGroup) Must

func (g *OptGroup) Must(name string) (value interface{})

Must is the same as Get(name), but panic if the option does not exist.

func (*OptGroup) MustBool

func (g *OptGroup) MustBool(name string) bool

MustBool is the same as GetBool(name), but panic if the option does not exist.

func (*OptGroup) MustDuration

func (g *OptGroup) MustDuration(name string) time.Duration

MustDuration is the same as GetDuration(name), but panic if the option does not exist.

func (*OptGroup) MustDurationSlice

func (g *OptGroup) MustDurationSlice(name string) []time.Duration

MustDurationSlice is the same as GetDurationSlice(name), but panic if the option does not exist.

func (*OptGroup) MustFloat64

func (g *OptGroup) MustFloat64(name string) float64

MustFloat64 is the same as GetFloat64(name), but panic if the option does not exist.

func (*OptGroup) MustFloat64Slice

func (g *OptGroup) MustFloat64Slice(name string) []float64

MustFloat64Slice is the same as GetFloat64Slice(name), but panic if the option does not exist.

func (*OptGroup) MustG

func (g *OptGroup) MustG(group string) *OptGroup

MustG is short for g.MustGroup(group).

func (*OptGroup) MustGroup

func (g *OptGroup) MustGroup(group string) *OptGroup

MustGroup is equal to g.Group(group), but panic if the group does not exist.

func (*OptGroup) MustInt

func (g *OptGroup) MustInt(name string) int

MustInt is the same as GetInt(name), but panic if the option does not exist.

func (*OptGroup) MustInt32

func (g *OptGroup) MustInt32(name string) int32

MustInt32 is the same as GetInt32(name), but panic if the option does not exist.

func (*OptGroup) MustInt64

func (g *OptGroup) MustInt64(name string) int64

MustInt64 is the same as GetInt64(name), but panic if the option does not exist.

func (*OptGroup) MustIntSlice

func (g *OptGroup) MustIntSlice(name string) []int

MustIntSlice is the same as GetIntSlice(name), but panic if the option does not exist.

func (*OptGroup) MustOpt

func (g *OptGroup) MustOpt(name string) Opt

MustOpt is the same as Opt(name), but panic if the option does not exist.

func (*OptGroup) MustString

func (g *OptGroup) MustString(name string) string

MustString is the same as GetString(name), but panic if the option does not exist.

func (*OptGroup) MustStringSlice

func (g *OptGroup) MustStringSlice(name string) []string

MustStringSlice is the same as GetStringSlice(name), but panic if the option does not exist.

func (*OptGroup) MustTime

func (g *OptGroup) MustTime(name string) time.Time

MustTime is the same as GetTime(name), but panic if the option does not exist.

func (*OptGroup) MustUint

func (g *OptGroup) MustUint(name string) uint

MustUint is the same as GetUint(name), but panic if the option does not exist.

func (*OptGroup) MustUint32

func (g *OptGroup) MustUint32(name string) uint32

MustUint32 is the same as GetUint32(name), but panic if the option does not exist.

func (*OptGroup) MustUint64

func (g *OptGroup) MustUint64(name string) uint64

MustUint64 is the same as GetUint64(name), but panic if the option does not exist.

func (*OptGroup) MustUintSlice

func (g *OptGroup) MustUintSlice(name string) []uint

MustUintSlice is the same as GetUintSlice(name), but panic if the option does not exist.

func (*OptGroup) Name

func (g *OptGroup) Name() string

Name returns the full name of the current group.

func (*OptGroup) NewGroup

func (g *OptGroup) NewGroup(group string) *OptGroup

NewGroup returns a new sub-group with the name named `group`.

Notice: If the sub-group has existed, it will return it instead.

func (*OptGroup) Opt

func (g *OptGroup) Opt(name string) (opt Opt, exist bool)

Opt returns the option named name.

func (*OptGroup) OptIsFrozen

func (g *OptGroup) OptIsFrozen(name string) (frozen bool)

OptIsFrozen reports whether the option named name is frozen.

Return false if the option does not exist.

func (*OptGroup) OptIsSet

func (g *OptGroup) OptIsSet(name string) bool

OptIsSet reports whether the option named name has been set.

func (*OptGroup) Parse

func (g *OptGroup) Parse(name string, value interface{}) (interface{}, error)

Parse the value of the option named name, which will call the parser and the validators of this option.

If no the option named `name`, it will return ErrNoOpt. If there is an other error, it will return an OptError.

func (*OptGroup) RegisterOpt

func (g *OptGroup) RegisterOpt(opt Opt, force ...bool) (ok bool)

RegisterOpt registers an option and returns true.

Notice: if the option has existed, it won't register it and return false. But you can set force to true to override it forcibly then to return true.

func (*OptGroup) RegisterOpts

func (g *OptGroup) RegisterOpts(opts []Opt, force ...bool) (ok bool)

RegisterOpts registers a set of options and returns true.

Notice: if a certain option has existed, it won't register them and return false. But you can set force to true to override it forcibly then to return true.

func (*OptGroup) RegisterStruct

func (g *OptGroup) RegisterStruct(v interface{})

RegisterStruct retusters the struct fields as the options into the current group.

Supproted types for the struct filed:

bool
int
int32
int64
uint
uint32
uint64
float64
string
time.Duration
time.Time
[]int
[]uint
[]float64
[]string
[]time.Duration
OptField<interface{}>

Other types will be ignored.

The tag of the field supports "name"(string), "short"(string), "help"(string), "default"(string), "group"(string).

  1. "name", "short", "default" and "help" are used to create a option with the name, the short name, the default value and the help doc.
  2. "group" is used to change the group of the option to "group". For a struct, if no "group", it will use "name".

If "name" or "group" is "-", that's `name:"-"` or `group:"-"`, the corresponding field will be ignored.

The bool value will be parsed by `strconv.ParseBool`, so "1", "t", "T", "TRUE", "true", "True", "0", "f", "F", "FALSE", "false" and "False" are accepted.

For the field that is a struct, it is a new sub-group of the current group, and the lower-case of the field name is the name of the new sub-group. But you can use the tag "group" or "name" to overwrite it, and "group" is preference to "name".

Notice:

  1. All the tags are optional.
  2. OptField is goroutine-safe, but the others is not.
  3. The struct must be a pointer to a struct variable, or panic.
  4. The struct supports the nested struct, but not the pointer field except OptField.
Example
type Group struct {
	Bool     bool          `help:"test bool"`
	Int      int           `default:"123" help:"test int"`
	Int32    int32         `default:"123" help:"test int32"`
	Int64    int64         `default:"123" help:"test int64"`
	Uint     uint          `default:"123" help:"test uint"`
	Uint32   uint32        `default:"123" help:"test uint32"`
	Uint64   uint64        `default:"123" help:"test uint64"`
	Float64  float64       `default:"123" help:"test float64"`
	String   string        `default:"abc" help:"test string"`
	Duration time.Duration `default:"123s" help:"test time.Duration"`
	Time     time.Time     `help:"test time.Time"`

	Ints      []int           `default:"1,2,3" help:"test []int"`
	Uints     []uint          `default:"1,2,3" help:"test []uint"`
	Float64s  []float64       `default:"1,2,3" help:"test []float64"`
	Strings   []string        `default:"a,b,c" help:"test []string"`
	Durations []time.Duration `default:"1s,2s,3s" help:"test []time.Duration"`
}

type WrapGroup struct {
	Bool     bool          `help:"test bool"`
	Int      int           `default:"456" help:"test int"`
	Int32    int32         `default:"456" help:"test int32"`
	Int64    int64         `default:"456" help:"test int64"`
	Uint     uint          `default:"456" help:"test uint"`
	Uint32   uint32        `default:"456" help:"test uint32"`
	Uint64   uint64        `default:"456" help:"test uint64"`
	Float64  float64       `default:"456" help:"test float64"`
	String   string        `default:"efg" help:"test string"`
	Duration time.Duration `default:"456s" help:"test time.Duration"`
	Time     time.Time     `help:"test time.Time"`

	Ints      []int           `default:"4,5,6" help:"test []int"`
	Uints     []uint          `default:"4,5,6" help:"test []uint"`
	Float64s  []float64       `default:"4,5,6" help:"test []float64"`
	Strings   []string        `default:"e,f,g" help:"test []string"`
	Durations []time.Duration `default:"4s,5s,6s" help:"test []time.Duration"`

	Group Group `group:"group3" name:"group33"`
}

type DataConfig struct {
	Bool     bool          `help:"test bool"`
	Int      int           `default:"789" help:"test int"`
	Int32    int32         `default:"789" help:"test int32"`
	Int64    int64         `default:"789" help:"test int64"`
	Uint     uint          `default:"789" help:"test uint"`
	Uint32   uint32        `default:"789" help:"test uint32"`
	Uint64   uint64        `default:"789" help:"test uint64"`
	Float64  float64       `default:"789" help:"test float64"`
	String   string        `default:"xyz" help:"test string"`
	Duration time.Duration `default:"789s" help:"test time.Duration"`
	Time     time.Time     `help:"test time.Time"`

	Ints      []int           `default:"7,8,9" help:"test []int"`
	Uints     []uint          `default:"7,8,9" help:"test []uint"`
	Float64s  []float64       `default:"7,8,9" help:"test []float64"`
	Strings   []string        `default:"x,y,z" help:"test []string"`
	Durations []time.Duration `default:"7s,8s,9s" help:"test []time.Duration"`

	Group1 Group     `group:"group1"`
	Group2 WrapGroup `name:"group2"`
}

// Register the option from struct
var data DataConfig
conf := New()
conf.RegisterStruct(&data)

// Add options to flag, and parse them from flag.
flagSet := flag.NewFlagSet("test_struct", flag.ExitOnError)
AddOptFlag(conf, flagSet)
flagSet.Parse([]string{
	"--bool=true",
	"--time=2019-06-11T20:00:00Z",
	"--group1.bool=1",
})
conf.LoadSource(NewFlagSource(flagSet))

fmt.Println("--- Struct ---")
fmt.Printf("bool: %t\n", data.Bool)
fmt.Printf("int: %d\n", data.Int)
fmt.Printf("int32: %d\n", data.Int32)
fmt.Printf("int64: %d\n", data.Int64)
fmt.Printf("uint: %d\n", data.Uint)
fmt.Printf("uint32: %d\n", data.Uint32)
fmt.Printf("uint64: %d\n", data.Uint64)
fmt.Printf("float64: %v\n", data.Float64)
fmt.Printf("string: %s\n", data.String)
fmt.Printf("duration: %s\n", data.Duration)
fmt.Printf("time: %s\n", data.Time)
fmt.Printf("ints: %v\n", data.Ints)
fmt.Printf("uints: %v\n", data.Uints)
fmt.Printf("float64s: %v\n", data.Float64s)
fmt.Printf("strings: %v\n", data.Strings)
fmt.Printf("durations: %v\n", data.Durations)
// ...
fmt.Println("--- Config ---")
fmt.Printf("bool: %t\n", conf.GetBool("bool"))
fmt.Printf("int: %d\n", conf.GetInt("int"))
fmt.Printf("int32: %d\n", conf.GetInt32("int32"))
fmt.Printf("int64: %d\n", conf.GetInt64("int64"))
fmt.Printf("uint: %d\n", conf.GetUint("uint"))
fmt.Printf("uint32: %d\n", conf.GetUint32("uint32"))
fmt.Printf("uint64: %d\n", conf.GetUint64("uint64"))
fmt.Printf("float64: %v\n", conf.GetFloat64("float64"))
fmt.Printf("string: %s\n", conf.GetString("string"))
fmt.Printf("duration: %s\n", conf.GetDuration("duration"))
fmt.Printf("time: %s\n", conf.GetTime("time"))
fmt.Printf("ints: %v\n", conf.GetIntSlice("ints"))
fmt.Printf("uints: %v\n", conf.GetUintSlice("uints"))
fmt.Printf("float64s: %v\n", conf.GetFloat64Slice("float64s"))
fmt.Printf("strings: %v\n", conf.GetStringSlice("strings"))
fmt.Printf("durations: %v\n", conf.GetDurationSlice("durations"))
// ...
conf.PrintGroup(os.Stdout)
Output:

--- Struct ---
bool: true
int: 789
int32: 789
int64: 789
uint: 789
uint32: 789
uint64: 789
float64: 789
string: xyz
duration: 13m9s
time: 2019-06-11 20:00:00 +0000 UTC
ints: [7 8 9]
uints: [7 8 9]
float64s: [7 8 9]
strings: [x y z]
durations: [7s 8s 9s]
--- Config ---
bool: true
int: 789
int32: 789
int64: 789
uint: 789
uint32: 789
uint64: 789
float64: 789
string: xyz
duration: 13m9s
time: 2019-06-11 20:00:00 +0000 UTC
ints: [7 8 9]
uints: [7 8 9]
float64s: [7 8 9]
strings: [x y z]
durations: [7s 8s 9s]
[DEFAULT]
    bool
    duration
    durations
    float64
    float64s
    int
    int32
    int64
    ints
    string
    strings
    time
    uint
    uint32
    uint64
    uints
[group1]
    bool
    duration
    durations
    float64
    float64s
    int
    int32
    int64
    ints
    string
    strings
    time
    uint
    uint32
    uint64
    uints
[group2]
    bool
    duration
    durations
    float64
    float64s
    int
    int32
    int64
    ints
    string
    strings
    time
    uint
    uint32
    uint64
    uints
[group2.group3]
    bool
    duration
    durations
    float64
    float64s
    int
    int32
    int64
    ints
    string
    strings
    time
    uint
    uint32
    uint64
    uints

func (*OptGroup) Set

func (g *OptGroup) Set(name string, value interface{})

Set parses and sets the option value named name in the current group to value.

For the option name, the characters "-" and "_" are equal, that's, "abcd-efg" is equal to "abcd_efg".

If there is not the option or the value is nil, it will ignore it.

func (*OptGroup) SetOptAlias

func (g *OptGroup) SetOptAlias(old, new string)

SetOptAlias sets the alias of the option from old to new. So you can access the option named new by the old name.

Notice: it does nothing if either is "".

Example
conf := New()
conf.RegisterOpt(IntOpt("newopt", "test alias").D(123))
conf.SetOptAlias("oldopt", "newopt")

fmt.Printf("newopt=%d, oldopt=%d\n", conf.GetInt("newopt"), conf.GetInt("oldopt"))
conf.Set("oldopt", 456)
fmt.Printf("newopt=%d, oldopt=%d\n", conf.GetInt("newopt"), conf.GetInt("oldopt"))
Output:

newopt=123, oldopt=123
newopt=456, oldopt=456

func (*OptGroup) UnfreezeGroup

func (g *OptGroup) UnfreezeGroup()

UnfreezeGroup unfreezes the current group and allows its options to be set.

If the current group has been unfrozen, it does nothing.

func (*OptGroup) UnfreezeOpt

func (g *OptGroup) UnfreezeOpt(names ...string)

UnfreezeOpt unfreeze these options and allows them to be set.

If the option does not exist has been unfrozen, it does nothing for it.

type SafeValue

type SafeValue struct {
	// contains filtered or unexported fields
}

SafeValue is used to set and get the value safely.

Notice: it is embedded in OptField in general.

func (*SafeValue) Get

func (sv *SafeValue) Get(_default interface{}) (value interface{})

Get returns the value safely.

func (*SafeValue) Set

func (sv *SafeValue) Set(v interface{})

Set updates the value to v safely.

type Source

type Source interface {
	// Read reads the source data once, which should not block.
	Read() (DataSet, error)

	// Watch watches the change of the source, then send the changed data to ds.
	//
	// The source can check whether close is closed to determine whether the
	// configuration is closed and to do any cleanup.
	Watch(load func(DataSet, error), close <-chan struct{})
}

Source represents a data source where the data is.

func NewCliSource

func NewCliSource(ctx *cli.Context, groups ...string) Source

NewCliSource returns a new source based on "github.com/urfave/cli", which will reads the configuration data from the flags of cli.

groups stands for the group that the context belongs on. The command name may be considered as the group name. The following ways are valid.

NewCliSource(ctx)                      // With the default global group
NewCliSource(ctx, "group1")            // With group "group1"
NewCliSource(ctx, "group1", "group2")  // With group "group1.group2"
NewCliSource(ctx, "group1.group2")     // With group "group1.group2"
Example
conf := New()
conf.RegisterOpt(StrOpt("opt1", "").D("abc"))
conf.NewGroup("cmd1").RegisterOpt(IntOpt("opt2", ""))
conf.NewGroup("cmd1").NewGroup("cmd2").RegisterOpt(IntOpt("opt3", ""))

app := cli.NewApp()
app.Flags = []cli.Flag{&cli.StringFlag{Name: "opt1"}}
app.Commands = []*cli.Command{
	{
		Name:  "cmd1",
		Flags: []cli.Flag{&cli.IntFlag{Name: "opt2"}},
		Subcommands: []*cli.Command{
			{
				Name:  "cmd2",
				Flags: []cli.Flag{&cli.IntFlag{Name: "opt3"}},
				Action: func(ctx *cli.Context) error {
					ctxs := ctx.Lineage()
					conf.LoadSource(NewCliSource(ctxs[0], "cmd1", "cmd2"))
					conf.LoadSource(NewCliSource(ctxs[1], "cmd1"))
					conf.LoadSource(NewCliSource(ctxs[2]))

					fmt.Println(conf.GetString("opt1"))
					fmt.Println(conf.Group("cmd1").GetInt("opt2"))
					fmt.Println(conf.Group("cmd1.cmd2").GetInt("opt3"))

					return nil
				},
			},
		},
	},
}

// For Test
app.Run([]string{"app", "--opt1=xyz", "cmd1", "--opt2=123", "cmd2", "--opt3=456"})
Output:

xyz
123
456

func NewEnvSource

func NewEnvSource(prefix ...string) Source

NewEnvSource returns a new env Source to read the configuration from the environment variables.

If giving the prefix, it will remove the prefix from the env key, then the rest is used for the option key.

Notice: It will convert all the underlines("_") to the dots(".").

func NewFileSource

func NewFileSource(filename string, defaultFormat ...string) Source

NewFileSource returns a new source that the data is read from the file named filename.

Notice: it will identify the format by the filename extension automatically. If no filename extension, it will use defaulFormat, which is "ini" by default.

func NewFlagSource

func NewFlagSource(flagSet ...*flag.FlagSet) Source

NewFlagSource returns a new source based on flag.FlagSet, which is flag.CommandLine by default.

func NewURLSource

func NewURLSource(url string, interval time.Duration, format ...string) Source

NewURLSource returns a url source to read the configuration data from the url by the stdlib http.Get(url).

The header "Content-Type" indicates the data format, that's, it will split the value by "/" and use the last part, such as "application/json" represents the format "json". But you can set format to override it.

It supports the watcher, which checks whether the data is changed once with interval time. If interval is 0, it is time.Minute by default.

func NewZkConnSource

func NewZkConnSource(conn *zk.Conn, path, format string, hosts ...string) Source

NewZkConnSource returns a new ZeeKeeper source with the connection to zk.

path is the prefix of the zk path. If path is "", it is "/" by default.

format is the format of the data of the zk source.

hosts is used to generate the id of the source. If missing, it will use conn.Server().

func NewZkSource

func NewZkSource(hosts []string, path, format string, timeout time.Duration, logger ...zk.Logger) Source

NewZkSource is the same as NewZkConnSource, and conn is created by hosts, timeout, logger.

type SourceError

type SourceError struct {
	Source string
	Format string
	Data   []byte
	Err    error
}

SourceError represents an error about the data source.

func NewSourceError

func NewSourceError(source, format string, data []byte, err error) SourceError

NewSourceError returns a new source error.

func (SourceError) Error

func (se SourceError) Error() string

type StringOptField

type StringOptField struct {
	// contains filtered or unexported fields
}

StringOptField represents the string option field of the struct.

func (*StringOptField) Default

func (f *StringOptField) Default() interface{}

Default implements OptField.Default().

func (*StringOptField) Get

func (f *StringOptField) Get() string

Get returns the value of the option field.

func (*StringOptField) Parse

func (f *StringOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*StringOptField) Set

func (f *StringOptField) Set(v interface{})

Set implements OptField.Set().

type StringSliceOptField

type StringSliceOptField struct {
	// contains filtered or unexported fields
}

StringSliceOptField represents the []string option field of the struct.

func (*StringSliceOptField) Default

func (f *StringSliceOptField) Default() interface{}

Default implements OptField.Default().

func (*StringSliceOptField) Get

func (f *StringSliceOptField) Get() []string

Get returns the value of the option field.

func (*StringSliceOptField) Parse

func (f *StringSliceOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*StringSliceOptField) Set

func (f *StringSliceOptField) Set(v interface{})

Set implements OptField.Set().

type TimeOptField

type TimeOptField struct {
	// contains filtered or unexported fields
}

TimeOptField represents the time.Time option field of the struct.

func (*TimeOptField) Default

func (f *TimeOptField) Default() interface{}

Default implements OptField.Default().

func (*TimeOptField) Get

func (f *TimeOptField) Get() time.Time

Get returns the value of the option field.

func (*TimeOptField) Parse

func (f *TimeOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*TimeOptField) Set

func (f *TimeOptField) Set(v interface{})

Set implements OptField.Set().

type Uint32OptField

type Uint32OptField struct {
	// contains filtered or unexported fields
}

Uint32OptField represents the uint32 option field of the struct.

func (*Uint32OptField) Default

func (f *Uint32OptField) Default() interface{}

Default implements OptField.Default().

func (*Uint32OptField) Get

func (f *Uint32OptField) Get() uint32

Get returns the value of the option field.

func (*Uint32OptField) Parse

func (f *Uint32OptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*Uint32OptField) Set

func (f *Uint32OptField) Set(v interface{})

Set implements OptField.Set().

type Uint64OptField

type Uint64OptField struct {
	// contains filtered or unexported fields
}

Uint64OptField represents the uint64 option field of the struct.

func (*Uint64OptField) Default

func (f *Uint64OptField) Default() interface{}

Default implements OptField.Default().

func (*Uint64OptField) Get

func (f *Uint64OptField) Get() uint64

Get returns the value of the option field.

func (*Uint64OptField) Parse

func (f *Uint64OptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*Uint64OptField) Set

func (f *Uint64OptField) Set(v interface{})

Set implements OptField.Set().

type UintOptField

type UintOptField struct {
	// contains filtered or unexported fields
}

UintOptField represents the uint option field of the struct.

func (*UintOptField) Default

func (f *UintOptField) Default() interface{}

Default implements OptField.Default().

func (*UintOptField) Get

func (f *UintOptField) Get() uint

Get returns the value of the option field.

func (*UintOptField) Parse

func (f *UintOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*UintOptField) Set

func (f *UintOptField) Set(v interface{})

Set implements OptField.Set().

type UintSliceOptField

type UintSliceOptField struct {
	// contains filtered or unexported fields
}

UintSliceOptField represents the []uint option field of the struct.

func (*UintSliceOptField) Default

func (f *UintSliceOptField) Default() interface{}

Default implements OptField.Default().

func (*UintSliceOptField) Get

func (f *UintSliceOptField) Get() []uint

Get returns the value of the option field.

func (*UintSliceOptField) Parse

func (f *UintSliceOptField) Parse(input interface{}) (output interface{}, err error)

Parse implements OptField.Parse().

func (*UintSliceOptField) Set

func (f *UintSliceOptField) Set(v interface{})

Set implements OptField.Set().

type Validator

type Validator func(value interface{}) error

Validator is used to validate whether the value of the option in the group is valid.

func NewAddressOrIPSliceValidator added in v4.2.0

func NewAddressOrIPSliceValidator() Validator

NewAddressOrIPSliceValidator returns a validator to validate whether the string element of the []string value is an address or ip.

func NewAddressOrIPValidator added in v4.2.0

func NewAddressOrIPValidator() Validator

NewAddressOrIPValidator is equal to NewAddressValidator, but it maybe miss the port.

func NewAddressSliceValidator

func NewAddressSliceValidator() Validator

NewAddressSliceValidator returns a validator to validate whether the string element of the []string value is a valid address.

func NewAddressValidator

func NewAddressValidator() Validator

NewAddressValidator returns a validator to validate whether an address is like "host:port", "host%zone:port", "[host]:port" or "[host%zone]:port".

This validator uses net.SplitHostPort() to validate it.

func NewEmailSliceValidator

func NewEmailSliceValidator() Validator

NewEmailSliceValidator returns a validator to validate whether the string element of the []string value is a valid email.

func NewEmailValidator

func NewEmailValidator() Validator

NewEmailValidator returns a validator to validate whether an email is valid.

func NewEmptyStrValidator

func NewEmptyStrValidator() Validator

NewEmptyStrValidator returns a validator to validate that the value must be an empty string.

func NewFloatRangeValidator

func NewFloatRangeValidator(min, max float64) Validator

NewFloatRangeValidator returns a validator to validate whether the float value is between the min and the max.

This validator can be used to validate the value of the type float32 and float64.

func NewIPSliceValidator

func NewIPSliceValidator() Validator

NewIPSliceValidator returns a validator to validate whether the string element of the []string value is a valid IP.

func NewIPValidator

func NewIPValidator() Validator

NewIPValidator returns a validator to validate whether an ip is valid.

func NewIntegerRangeValidator

func NewIntegerRangeValidator(min, max int64) Validator

NewIntegerRangeValidator returns a validator to validate whether the integer value is between the min and the max.

This validator can be used to validate the value of the type int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64.

func NewMaybeAddressOrIPValidator added in v4.2.0

func NewMaybeAddressOrIPValidator() Validator

NewMaybeAddressOrIPValidator returns a validator to validate the value may be empty or an address or an ip.

func NewMaybeAddressValidator added in v4.2.0

func NewMaybeAddressValidator() Validator

NewMaybeAddressValidator returns a validator to validate the value may be empty or an address.

func NewMaybeEmailValidator added in v4.2.0

func NewMaybeEmailValidator() Validator

NewMaybeEmailValidator returns a validator to validate the value may be empty or an email.

func NewMaybeIPValidator added in v4.2.0

func NewMaybeIPValidator() Validator

NewMaybeIPValidator returns a validator to validate the value may be empty or a ip.

func NewMaybeURLValidator added in v4.2.0

func NewMaybeURLValidator() Validator

NewMaybeURLValidator returns a validator to validate the value may be empty or a URL.

func NewPortValidator

func NewPortValidator() Validator

NewPortValidator returns a validator to validate whether a port is between 0 and 65535.

func NewRegexpValidator

func NewRegexpValidator(pattern string) Validator

NewRegexpValidator returns a validator to validate whether the value match the regular expression.

This validator uses regexp.MatchString(pattern, s) to validate it.

func NewStrArrayValidator

func NewStrArrayValidator(array []string) Validator

NewStrArrayValidator returns a validator to validate that the value is in the array.

func NewStrLenValidator

func NewStrLenValidator(min, max int) Validator

NewStrLenValidator returns a validator to validate that the length of the string must be between min and max.

func NewStrNotEmptyValidator

func NewStrNotEmptyValidator() Validator

NewStrNotEmptyValidator returns a validator to validate that the value must not be an empty string.

func NewStrSliceValidator

func NewStrSliceValidator(strValidators ...Validator) Validator

NewStrSliceValidator returns a validator to validate whether the string element of the []string value satisfies all the given validators.

func NewURLSliceValidator

func NewURLSliceValidator() Validator

NewURLSliceValidator returns a validator to validate whether the string element of the []string value is a valid URL.

func NewURLValidator

func NewURLValidator() Validator

NewURLValidator returns a validator to validate whether a url is valid.

func Or

func Or(validators ...Validator) Validator

Or returns a union validator, which returns nil only if a certain validator returns nil or the error that the last validator returns.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL