配置模块

配置模块是基础模块之一,对不同类型的配置文件提供了一种抽象。该章节内容都可以在配置模块例子(opens new window)

Beego 目前支持 INI、XML、JSON、YAML 格式的配置文件解析,也支持以 etcd 作为远程配置中心。默认采用了 INI 格式解析,用户可以通过简单的配置就可以获得很大的灵活性。

它们拥有的方法都是一样的,具体可以参考Config API (opens new window)。主要方法有:

  1. // Configer defines how to get and set value from configuration raw data.
  2. type Configer interface {
  3. // support section::key type in given key when using ini type.
  4. Set(key, val string) error
  5. // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
  6. String(key string) (string, error)
  7. // get string slice
  8. Strings(key string) ([]string, error)
  9. Int(key string) (int, error)
  10. Int64(key string) (int64, error)
  11. Bool(key string) (bool, error)
  12. Float(key string) (float64, error)
  13. // support section::key type in key string when using ini and json type; Int,Int64,Bool,Float,DIY are same.
  14. DefaultString(key string, defaultVal string) string
  15. // get string slice
  16. DefaultStrings(key string, defaultVal []string) []string
  17. DefaultInt(key string, defaultVal int) int
  18. DefaultInt64(key string, defaultVal int64) int64
  19. DefaultBool(key string, defaultVal bool) bool
  20. DefaultFloat(key string, defaultVal float64) float64
  21. // DIY return the original value
  22. DIY(key string) (interface{}, error)
  23. GetSection(section string) (map[string]string, error)
  24. Unmarshaler(prefix string, obj interface{}, opt ...DecodeOption) error
  25. Sub(key string) (Configer, error)
  26. OnChange(key string, fn func(value string))
  27. SaveConfigFile(filename string) error
  28. }

这里有一些使用的注意事项:

  1. 所有的Default*方法,在key不存在,或者查找的过程中,出现error,都会返回默认值;
  2. DIY直接返回对应的值,而没有做任何类型的转换。当你使用这个方法的时候,你应该自己确认值的类型。只有在极少数的情况下你才应该考虑使用这个方法;
  3. GetSection会返回section所对应的部分配置。section如何被解释,取决于具体的实现;
  4. Unmarshaler会尝试用当且配置的值来初始化obj。需要注意的是,prefix的概念类似于section
  5. Sub类似与GetSection,都是尝试返回配置的一部分。所不同的是,GetSection将结果组织成map,而Sub将结果组织成Config实例;
  6. OnChange主要用于监听配置的变化。对于大部分依赖于文件系统的实现来说,都不支持。具体而言,我们设计这个主要是为了考虑支持远程配置;
  7. SaveConfigFile尝试将配置导出成为一个文件;
  8. 某些实现支持分段式的key。比如说a.b.c这种,但是,并不是所有的实现都支持,也不是所有的实现都采用.作为分隔符。这是一个历史遗留问题,为了保留兼容性,我们无法在这方面保持一致。

Web 模块封装了配置模块,可以参考Web 配置

初始化方法

大致上有两种用法:

  • 使用config.XXXX:这是依赖于全局配置实例
  • 使用Configer实例

全局实例

Beego 默认会解析当前应用下的 conf/app.conf 文件,后面就可以通过config包名直接使用:

  1. import (
  2. "github.com/beego/beego/v2/core/config"
  3. "github.com/beego/beego/v2/core/logs"
  4. )
  5. func main() {
  6. val, _ := config.String("name")
  7. logs.Info("auto load config name is", val)
  8. }

也可以手动初始化全局实例,以指定不同的配置类型,例如说启用etcd

  1. config.InitGlobalInstance("etcd", "etcd address")

使用Configer实例

如果要从多个源头读取配置,或者说自己不想依赖于全局配置,那么可以自己初始化一个配置实例:

  1. func main() {
  2. cfg, err := config.NewConfig("ini", "my_config.ini")
  3. if err != nil {
  4. logs.Error(err)
  5. }
  6. val, _ := cfg.String("appname")
  7. logs.Info("auto load config name is", val)
  8. }

环境变量支持

配置文件解析支持从环境变量中获取配置项,配置项格式:${环境变量}。例如下面的配置中优先使用环境变量中配置的 runmode 和 httpport,如果有配置环境变量 ProRunMode 则优先使用该环境变量值。如果不存在或者为空,则使用 “dev” 作为 runmode。例如使用 INI 的时候指定环境变量:

  1. runmode = "${ProRunMode||dev}"
  2. httpport = "${ProPort||9090}"

支持的格式

注意,所以的相对文件路径,都是从你的工作目录开始计算! 其次,除了默认的 INI 格式,其余格式都需要采用匿名引入的方式引入对应的包。

INI 格式

INI 是配置模块的默认格式。同时它支持使用include的方式,加载多个配置文件。

app.ini:

  1. appname = beepkg
  2. httpaddr = "127.0.0.1"
  3. httpport = 9090
  4. include "app2.ini"

app2.ini:

  1. runmode ="dev"
  2. autorender = false
  3. recoverpanic = false
  4. viewspath = "myview"
  5. [dev]
  6. httpport = 8080
  7. [prod]
  8. httpport = 8088
  9. [test]
  10. httpport = 8888
  11. func main() {
  12. cfg, err := config.NewConfig("ini", "app.ini")
  13. if err != nil {
  14. logs.Error(err)
  15. }
  16. val, _ := cfg.String("appname")
  17. logs.Info("auto load config name is", val)
  18. }

JSON

JSON 只需要指定格式,并且不要忘了使用匿名引入的方式引入 JSON 的实现:

  1. import (
  2. "github.com/beego/beego/v2/core/config"
  3. // 千万不要忘了
  4. _ "github.com/beego/beego/v2/core/config/json"
  5. "github.com/beego/beego/v2/core/logs"
  6. )
  7. var (
  8. ConfigFile = "./app.json"
  9. )
  10. func main() {
  11. err := config.InitGlobalInstance("json", ConfigFile)
  12. if err != nil {
  13. logs.Critical("An error occurred:", err)
  14. panic(err)
  15. }
  16. val, _ := config.String("name")
  17. logs.Info("load config name is", val)
  18. }

YAML

别忘了匿名引入 YAML 的实现!

  1. import (
  2. "github.com/beego/beego/v2/core/config"
  3. // never forget this
  4. _ "github.com/beego/beego/v2/core/config/yaml"
  5. "github.com/beego/beego/v2/core/logs"
  6. )
  7. var (
  8. ConfigFile = "./app.yaml"
  9. )
  10. func main() {
  11. err := config.InitGlobalInstance("yaml", ConfigFile)
  12. if err != nil {
  13. logs.Critical("An error occurred:", err)
  14. panic(err)
  15. }
  16. val, _ := config.String("name")
  17. logs.Info("load config name is", val)
  18. }

XML

别忘了匿名引入 XML 的实现!

  1. import (
  2. "github.com/beego/beego/v2/core/config"
  3. // never forget this
  4. _ "github.com/beego/beego/v2/core/config/xml"
  5. "github.com/beego/beego/v2/core/logs"
  6. )
  7. var (
  8. ConfigFile = "./app.xml"
  9. )
  10. func main() {
  11. err := config.InitGlobalInstance("xml", ConfigFile)
  12. if err != nil {
  13. logs.Critical("An error occurred:", err)
  14. panic(err)
  15. }
  16. val, _ := config.String("name")
  17. logs.Info("load config name is", val)
  18. }

要注意,所有的配置项都要放在config这个顶级节点之内:

  1. <?xml version="1.0" encoding="UTF-8" ?>
  2. <config>
  3. <name>beego</name>
  4. </config>

TOML

别忘了匿名引入 TOML 的实现!

  1. import (
  2. "github.com/beego/beego/v2/core/config"
  3. // never forget this
  4. _ "github.com/beego/beego/v2/core/config/toml"
  5. "github.com/beego/beego/v2/core/logs"
  6. )
  7. var (
  8. ConfigFile = "./app.toml"
  9. )
  10. func main() {
  11. err := config.InitGlobalInstance("toml", ConfigFile)
  12. if err != nil {
  13. logs.Critical("An error occurred:", err)
  14. panic(err)
  15. }
  16. val, _ := config.String("name")
  17. logs.Info("load config name is", val)
  18. }

Etcd

别忘了匿名引入 ETCD 的实现!

  1. import (
  2. "github.com/beego/beego/v2/core/config"
  3. // never forget this
  4. _ "github.com/beego/beego/v2/core/config/toml"
  5. "github.com/beego/beego/v2/core/logs"
  6. )
  7. func main() {
  8. err := config.InitGlobalInstance("etcd", "your_config")
  9. if err != nil {
  10. logs.Critical("An error occurred:", err)
  11. panic(err)
  12. }
  13. val, _ := config.String("name")
  14. logs.Info("load config name is", val)
  15. }

其中 your_config 是一个 JSON 配置,它对应于:

  1. type Config struct {
  2. // Endpoints is a list of URLs.
  3. Endpoints []string `json:"endpoints"`
  4. // AutoSyncInterval is the interval to update endpoints with its latest members.
  5. // 0 disables auto-sync. By default auto-sync is disabled.
  6. AutoSyncInterval time.Duration `json:"auto-sync-interval"`
  7. // DialTimeout is the timeout for failing to establish a connection.
  8. DialTimeout time.Duration `json:"dial-timeout"`
  9. // DialKeepAliveTime is the time after which client pings the server to see if
  10. // transport is alive.
  11. DialKeepAliveTime time.Duration `json:"dial-keep-alive-time"`
  12. // DialKeepAliveTimeout is the time that the client waits for a response for the
  13. // keep-alive probe. If the response is not received in this time, the connection is closed.
  14. DialKeepAliveTimeout time.Duration `json:"dial-keep-alive-timeout"`
  15. // MaxCallSendMsgSize is the client-side request send limit in bytes.
  16. // If 0, it defaults to 2.0 MiB (2 * 1024 * 1024).
  17. // Make sure that "MaxCallSendMsgSize" < server-side default send/recv limit.
  18. // ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
  19. MaxCallSendMsgSize int
  20. // MaxCallRecvMsgSize is the client-side response receive limit.
  21. // If 0, it defaults to "math.MaxInt32", because range response can
  22. // easily exceed request send limits.
  23. // Make sure that "MaxCallRecvMsgSize" >= server-side default send/recv limit.
  24. // ("--max-request-bytes" flag to etcd or "embed.Config.MaxRequestBytes").
  25. MaxCallRecvMsgSize int
  26. // TLS holds the client secure credentials, if any.
  27. TLS *tls.Config
  28. // Username is a user name for authentication.
  29. Username string `json:"username"`
  30. // Password is a password for authentication.
  31. Password string `json:"password"`
  32. // RejectOldCluster when set will refuse to create a client against an outdated cluster.
  33. RejectOldCluster bool `json:"reject-old-cluster"`
  34. // DialOptions is a list of dial options for the grpc client (e.g., for interceptors).
  35. // For example, pass "grpc.WithBlock()" to block until the underlying connection is up.
  36. // Without this, Dial returns immediately and connecting the server happens in background.
  37. DialOptions []grpc.DialOption
  38. // Context is the default client context; it can be used to cancel grpc dial out and
  39. // other operations that do not have an explicit context.
  40. Context context.Context
  41. // Logger sets client-side logger.
  42. // If nil, fallback to building LogConfig.
  43. Logger *zap.Logger
  44. // LogConfig configures client-side logger.
  45. // If nil, use the default logger.
  46. // TODO: configure gRPC logger
  47. LogConfig *zap.Config
  48. // PermitWithoutStream when set will allow client to send keepalive pings to server without any active streams(RPCs).
  49. PermitWithoutStream bool `json:"permit-without-stream"`
  50. // TODO: support custom balancer picker
  51. }