# Configure Module
Configure module is the core module which provides an abstraction layer for different configuration sources or formats.
You can find the examples here (opens new window)
Currently, Beego support all major configure formats, including INI (by default), XML, JSON, YAML and remote configure center etcd
.
Config API (opens new window):
// Configer defines how to get and set value from configuration raw data.
type Configer interface {
// support section::key type in given key when using ini type.
Set(key, val string) error
// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
String(key string) (string, error)
// get string slice
Strings(key string) ([]string, error)
Int(key string) (int, error)
Int64(key string) (int64, error)
Bool(key string) (bool, error)
Float(key string) (float64, error)
// support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
DefaultString(key string, defaultVal string) string
// get string slice
DefaultStrings(key string, defaultVal []string) []string
DefaultInt(key string, defaultVal int) int
DefaultInt64(key string, defaultVal int64) int64
DefaultBool(key string, defaultVal bool) bool
DefaultFloat(key string, defaultVal float64) float64
// DIY return the original value
DIY(key string) (interface{}, error)
GetSection(section string) (map[string]string, error)
Unmarshaler(prefix string, obj interface{}, opt ...DecodeOption) error
Sub(key string) (Configer, error)
OnChange(key string, fn func(value string))
SaveConfigFile(filename string) error
}
Notices:
- All
Default*
methods will return the default value, if the key does not exist or an error occured. DIY
returns the value directly without any conversion.GetSection
returns all configuration of the specificsection
, and it depends on the implementation details.Unmarshaler
tries to use the configuration value to initiate theobj
.prefix
is similar tosection
.Sub
is similar toGetSection
, which tries to return all configuration of the specificsection
. The difference is thatGetSection
returns the values asmap
, butSub
returns the values asConfig
instance.OnChange
subscribes the change the configuration. But most of the implementations which are based on file system do not support this methods. In general, we prefer to use this for configure center like etcd.SaveConfigFile
writes all configuration into file(s).- Some implementations support the key like
a.b.c
while some DO NOT. Besides, some implementations choose the.
as separator, while some choose other characters. This is a historical problem and we cannot make them consistent, if we keep backward compatible.
Web module re-encapsulates the configuration module. For more details, please refer to Web Module Configuration
# Initiate
There are two major ways to use the configuration module:
- Use package functions
config.XXXX
, which relies on the global instance - Initiate
Configer
instances
# Global instance
Beego will try to parse the file conf/app.conf
so that you can use the package functions:
import (
"github.com/beego/beego/v2/core/config"
"github.com/beego/beego/v2/core/logs"
)
func main() {
val, _ := config.String("name")
logs.Info("auto load config name is", val)
}
Or you can initiate the global instance manually to specify the source:
config.InitGlobalInstance("etcd", "etcd address")
# Initiate Configer
instances
If you do not want to use the global instance, you can initiate the Configer
instances manually:
func main() {
cfg, err := config.NewConfig("ini", "my_config.ini")
if err != nil {
logs.Error(err)
}
val, _ := cfg.String("appname")
logs.Info("auto load config name is", val)
}
# Environment variable
The format for this is ${ENVIRONMENTVARIABLE}
within the configuration file, which is equivalent to value = os.Getenv('ENVIRONMENTVARIABLE')
. Beego will only check for environment variables, if the value begins with ${
and ends with }
.
Additionally, a default value can be configured in case that there is no environment variable set or the environment variable is empty. This is accomplished by using the format ${ENVVAR||defaultvalue}
:
runmode = "${ProRunMode||dev}"
httpport = "${ProPort||9090}"
# Implementations
Note that all relative file paths, are calculated from your working directory! Secondly, except for the default INI implementation, all other implementations need to be introduced using anonymous introduction of the corresponding package.
# INI
INI is the default implementation for configuring modules. It also supports loading multiple configuration files using the include
syntax.
app.ini:
appname = beepkg
httpaddr = "127.0.0.1"
httpport = 9090
include "app2.ini"
app2.ini:
runmode ="dev"
autorender = false
recoverpanic = false
viewspath = "myview"
[dev]
httpport = 8080
[prod]
httpport = 8088
[test]
httpport = 8888
func main() {
cfg, err := config.NewConfig("ini", "app.ini")
if err != nil {
logs.Error(err)
}
val, _ := cfg.String("appname")
logs.Info("auto load config name is", val)
}
# JSON
import (
"github.com/beego/beego/v2/core/config"
// DO NOT FORGET THIS
_ "github.com/beego/beego/v2/core/config/json"
"github.com/beego/beego/v2/core/logs"
)
var (
ConfigFile = "./app.json"
)
func main() {
err := config.InitGlobalInstance("json", ConfigFile)
if err != nil {
logs.Critical("An error occurred:", err)
panic(err)
}
val, _ := config.String("name")
logs.Info("load config name is", val)
}
# YAML
import (
"github.com/beego/beego/v2/core/config"
// never forget this
_ "github.com/beego/beego/v2/core/config/yaml"
"github.com/beego/beego/v2/core/logs"
)
var (
ConfigFile = "./app.yaml"
)
func main() {
err := config.InitGlobalInstance("yaml", ConfigFile)
if err != nil {
logs.Critical("An error occurred:", err)
panic(err)
}
val, _ := config.String("name")
logs.Info("load config name is", val)
}
# XML
import (
"github.com/beego/beego/v2/core/config"
// never forget this
_ "github.com/beego/beego/v2/core/config/xml"
"github.com/beego/beego/v2/core/logs"
)
var (
ConfigFile = "./app.xml"
)
func main() {
err := config.InitGlobalInstance("xml", ConfigFile)
if err != nil {
logs.Critical("An error occurred:", err)
panic(err)
}
val, _ := config.String("name")
logs.Info("load config name is", val)
}
Note that all configuration items should be placed within the root config
:
<?xml version="1.0" encoding="UTF-8" ?>
<config>
<name>beego</name>
</config>
# TOML
import (
"github.com/beego/beego/v2/core/config"
// never forget this
_ "github.com/beego/beego/v2/core/config/toml"
"github.com/beego/beego/v2/core/logs"
)
var (
ConfigFile = "./app.toml"
)
func main() {
err := config.InitGlobalInstance("toml", ConfigFile)
if err != nil {
logs.Critical("An error occurred:", err)
panic(err)
}
val, _ := config.String("name")
logs.Info("load config name is", val)
}
# Etcd
import (
"github.com/beego/beego/v2/core/config"
// never forget this
_ "github.com/beego/beego/v2/core/config/toml"
"github.com/beego/beego/v2/core/logs"
)
func main() {
err := config.InitGlobalInstance("etcd", "your_config")
if err != nil {
logs.Critical("An error occurred:", err)
panic(err)
}
val, _ := config.String("name")
logs.Info("load config name is", val)
}
where your_config
is a JSON configuration that corresponds to:
type Config struct {
// Endpoints is a list of URLs.
Endpoints []string `json:"endpoints"`
// AutoSyncInterval is the interval to update endpoints with its latest members.
// 0 disables auto-sync. By default auto-sync is disabled.
AutoSyncInterval time.Duration `json:"auto-sync-interval"`
// DialTimeout is the timeout for failing to establish a connection.
DialTimeout time.Duration `json:"dial-timeout"`
// DialKeepAliveTime is the time after which client pings the server to see if
// transport is alive.
DialKeepAliveTime time.Duration `json:"dial-keep-alive-time"`
// DialKeepAliveTimeout is the time that the client waits for a response for the
// keep-alive probe. If the response is not received in this time, the connection is closed.
DialKeepAliveTimeout time.Duration `json:"dial-keep-alive-timeout"`
// MaxCallSendMsgSize is the client-side request send limit in bytes.
// If 0, it defaults to 2.0 MiB (2 * 1024 * 1024).
// Make sure that "MaxCallSendMsgSize" < server-side default send/recv limit.
// ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
MaxCallSendMsgSize int
// MaxCallRecvMsgSize is the client-side response receive limit.
// If 0, it defaults to "math.MaxInt32", because range response can
// easily exceed request send limits.
// Make sure that "MaxCallRecvMsgSize" >= server-side default send/recv limit.
// ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
MaxCallRecvMsgSize int
// TLS holds the client secure credentials, if any.
TLS *tls.Config
// Username is a user name for authentication.
Username string `json:"username"`
// Password is a password for authentication.
Password string `json:"password"`
// RejectOldCluster when set will refuse to create a client against an outdated cluster.
RejectOldCluster bool `json:"reject-old-cluster"`
// DialOptions is a list of dial options for the grpc client (e.g., for interceptors).
// For example, pass "grpc.WithBlock()" to block until the underlying connection is up.
// Without this, Dial returns immediately and connecting the server happens in background.
DialOptions []grpc.DialOption
// Context is the default client context; it can be used to cancel grpc dial out and
// other operations that do not have an explicit context.
Context context.Context
// Logger sets client-side logger.
// If nil, fallback to building LogConfig.
Logger *zap.Logger
// LogConfig configures client-side logger.
// If nil, use the default logger.
// TODO: configure gRPC logger
LogConfig *zap.Config
// PermitWithoutStream when set will allow client to send keepalive pings to server without any active streams(RPCs).
PermitWithoutStream bool `json:"permit-without-stream"`
// TODO: support custom balancer picker
}