gconf

package module
Version: v5.2.0 Latest Latest
Warning

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

Go to latest
Published: Apr 8, 2021 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.

Install

$ go get -u github.com/xgfone/gconf/v5

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/v5"
)

func main() {
	// Register options
	conf := gconf.New()
	conf.RegisterOpts(gconf.StrOpt("ip", "the ip address").D("0.0.0.0").V(gconf.NewIPValidator()))
	conf.RegisterOpts(gconf.IntOpt("port", "the port").D(80))
	conf.NewGroup("redis").RegisterOpts(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(conf.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/v5"
)

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/v5"
)

func main() {
	// Register the options
	gconf.RegisterOpts(gconf.StrOpt("opt1", "").D("abc"))
	gconf.NewGroup("group").RegisterOpts(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/v2"
	"github.com/xgfone/gconf/v5"
)

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

	// Create and run cli app.
	app := cli.NewApp()
	app.Flags = gconf.ConvertOptsToCliFlags(gconf.Conf.OptGroup)
	app.Commands = []*cli.Command{
		{
			Name:  "cmd1",
			Flags: gconf.ConvertOptsToCliFlags(gconf.Group("cmd1")),
			Subcommands: []*cli.Command{
				{
					Name:  "cmd2",
					Flags: gconf.ConvertOptsToCliFlags(gconf.Group("cmd1.cmd2")),
					Action: func(ctx *cli.Context) error {
						// Load the sources
						ctxs := ctx.Lineage()
						gconf.LoadSource(gconf.NewCliSource(ctxs[0], "cmd1", "cmd2")) // cmd2
						gconf.LoadSource(gconf.NewCliSource(ctxs[1], "cmd1"))         // cmd1
						gconf.LoadSource(gconf.NewCliSource(ctxs[2]))                 // 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/v5"
)

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/v5"
)

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/v5"
    "github.com/xgfone/gconf/v5/field"
)

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

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

func main() {
	// Notice: for the pointer to the option field, it must be initialized.
	// Or it will be ignored.
	config := AppConfig{IntP: &field.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 is the same as AddOptFlag, but parses the CLI arguments.

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.

Notice: for the slice option, it maybe occur many times, and they are combined with the comma as the string representation of slice. For example,

$APP --slice-opt v1  --slice-opt v2  --slice-opt v3
$APP --slice-opt v1,v2  --slice-opt v3
$APP --slice-opt v1,v2,v3

They are equivalent.

func Args added in v5.1.0

func Args() []string

Args is equal to Conf.Args().

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) error

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

func LoadDataSetCallback

func LoadDataSetCallback(ds DataSet, err error) bool

LoadDataSetCallback is equal to Conf.LoadDataSetCallback(ds, err).

func LoadMap

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

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 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 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 RegisterOpts

func RegisterOpts(opts ...Opt)

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

func RegisterStruct

func RegisterStruct(v interface{})

RegisterStruct is equal to Conf.RegisterStruct(v).

func SetArgs added in v5.1.0

func SetArgs(args []string)

SetArgs is equal to Conf.SetArgs(args).

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 UnregisterOpts

func UnregisterOpts(opts ...Opt)

UnregisterOpts is equal to Conf.UnregisterOpts(opts...).

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 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").UTC())
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").UTC())
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").UTC())
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) Args added in v5.1.0

func (c *Config) Args() []string

Args returns the rest CLI arguments.

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) (err error)

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) LoadDataSetCallback

func (c *Config) LoadDataSetCallback(ds DataSet, err error) bool

LoadDataSetCallback is a callback used by the watcher.

func (*Config) LoadMap

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

LoadMap loads the configuration options from the map m and returns true only if all options are parsed and set successfully.

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"
}

func (*Config) LoadSource

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

LoadSource loads the sources, and call Watch to watch the source, which is equal to

c.LoadSourceWithoutWatch(source, force...)
source.Watch(c.LoadDataSetCallback, c.CloseNotice())

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) 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.RegisterOpts(StrOpt("opt1", "").D("abc"))
conf.NewGroup("group").RegisterOpts(IntOpt("opt2", "").D(123))
conf.Group("group").NewGroup("subgroup").RegisterOpts(IntOpt("opt3", ""))
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)
conf.Group("group").Group("subgroup").Set("opt3", 456)
Output:

Setting: group=, opt=opt1, old=abc, new=xyz
Setting: group=group, opt=opt2, old=123, new=789
Setting: group=group.subgroup, opt=opt3, old=0, new=456

func (*Config) PrintGroup

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

PrintGroup prints the information of all groups to w.

func (*Config) SetArgs added in v5.1.0

func (c *Config) SetArgs(args []string)

SetArgs sets the rest CLI arguments to args.

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.

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 excpet for the their default values.

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.RegisterOpts(StrOpt("opt1", ""))
conf.NewGroup("group1").RegisterOpts(IntOpt("opt2", ""))
conf.NewGroup("group1").NewGroup("group2").RegisterOpts(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:

{}
{"opt1":"abc"}
{"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.RegisterOpts(StrOpt("opt1", "").D("abc"))
conf.NewGroup("group1").RegisterOpts(IntOpt("opt2", "").D(123))
conf.NewGroup("group1").NewGroup("group2").RegisterOpts(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{}) (err error)

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{}) error

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 {
	Args      []string  // The CLI arguments filled by the CLI source such as flag.
	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.
}

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"
	//     }
	//
	// Notice: 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 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

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(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      field.BoolOptField
	BoolT     field.BoolTOptField
	Int       field.IntOptField
	Int32     field.Int32OptField
	Int64     field.Int64OptField
	Uint      field.UintOptField
	Uint32    field.Uint32OptField
	Uint64    field.Uint64OptField
	Float64   field.Float64OptField
	String    field.StringOptField
	Duration  field.DurationOptField
	Time      field.TimeOptField
	Ints      field.IntSliceOptField
	Uints     field.UintSliceOptField
	Float64s  field.Float64SliceOptField
	Strings   field.StringSliceOptField
	Durations field.DurationSliceOptField

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

// Notice: for the pointer to the option field, it must be initialized.
// Or it will be ignored.
config := AppConfig{IntP: &field.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().UTC().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-27T15:39:34Z")
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().UTC().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(StrOpt("opt1", "").D("a"), StrOpt("opt2", "").D("b"))
conf.NewGroup("group2").RegisterOpts(StrOpt("opt3", "").D("c"), StrOpt("opt4", "").D("d"))
conf.Group("group1").FreezeOpt("opt2")
conf.Group("group2").FreezeGroup()

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

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:

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

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.RegisterOpts(StrOpt("opt1", "").D("abc"))
conf.RegisterOpts(StrOpt("opt2", "").D("efg"))
conf.NewGroup("group1").RegisterOpts(StrOpt("opt3", "").D("opq"))
conf.NewGroup("group1").RegisterOpts(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) RegisterOpts

func (g *OptGroup) RegisterOpts(opts ...Opt)

RegisterOpts registers a set of options and returns true.

Notice: if a certain option has existed, it will panic.

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 := gconf.New()
conf.RegisterStruct(&data)

// Add options to flag, and parse them from flag.
flagSet := flag.NewFlagSet("test_struct", flag.ExitOnError)
gconf.AddOptFlag(conf, flagSet)
flagSet.Parse([]string{
	"--bool=true",
	"--time=2019-06-11T20:00:00Z",
	"--group1.bool=1",
})
conf.LoadSource(gconf.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.UTC())
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").UTC())
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{}) error

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.RegisterOpts(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.

func (*OptGroup) UnregisterOpts

func (g *OptGroup) UnregisterOpts(opts ...Opt)

UnregisterOpts unregisters the registered options.

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.
	//
	// Notice: load returns true only the DataSet is loaded successfully.
	Watch(load func(DataSet, error) bool, 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.RegisterOpts(StrOpt("opt1", "").D("abc"))
conf.NewGroup("cmd1").RegisterOpts(IntOpt("opt2", ""))
conf.NewGroup("cmd1").NewGroup("cmd2").RegisterOpts(IntOpt("opt3", ""))

app := cli.NewApp()
app.Flags = ConvertOptsToCliFlags(conf.OptGroup)
app.Commands = []*cli.Command{
	{
		Name:  "cmd1",
		Flags: ConvertOptsToCliFlags(conf.Group("cmd1")),
		Subcommands: []*cli.Command{
			{
				Name:  "cmd2",
				Flags: ConvertOptsToCliFlags(conf.Group("cmd1.cmd2")),
				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 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

func NewAddressOrIPSliceValidator() Validator

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

func NewAddressOrIPValidator

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

func NewMaybeAddressOrIPValidator() Validator

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

func NewMaybeAddressValidator

func NewMaybeAddressValidator() Validator

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

func NewMaybeEmailValidator

func NewMaybeEmailValidator() Validator

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

func NewMaybeIPValidator

func NewMaybeIPValidator() Validator

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

func NewMaybeURLValidator

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.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
t or T : Toggle theme light dark auto
y or Y : Canonical URL