Tendermint需要配置一些属性的时候是在config.toml中配置的,刚开始没看明白toml配置文件是如何生效的,深入了解了一下做个记录。
原来tnedermint使用了viper(ˈvaɪpə(r),现在看到i都得确认下发什么音)开源项目,那么viper是什么呢
看下github的解释:https://github.com/spf13/viper
Viper is a complete configuration solution for Go applications including 12-Factor apps. It is designed to work within an application, and can handle all types of configuration needs and formats. It supports:
setting defaults
reading from JSON, TOML, YAML, HCL, and Java properties config files
live watching and re-reading of config files (optional)
reading from environment variables
reading from remote config systems (etcd or Consul), and watching changes
reading from command line flags
reading from buffer
setting explicit values
Viper can be thought of as a registry for all of your applications configuration needs.
(csdn改版了啊,这个框可以再编辑了,以前没法编辑,需要更改里面的代码还需要删除重新添加才可以,赞一个)
意思就是Viper是一个基于Go语言的全功能的配置解决方案。就是如果你的程序需要一些配置属性,它都可以做到。
这么来看viper其实就是类似一个库的功能了,那么对于库的使用我们还是比较熟悉的,那么就从使用库的角度来介绍下Viper是如何使用的吧,然后再找机会深入分析
(csdn有bug啊,写完了之后直接点了发布博客,有的内容没有保存,导致有丢失。可能需要先点击保存修改才可以。本来文章都写完了发现没有了,心都拔凉拔凉的,稍微补一点吧)
// Bind all flags and read the config into viper
func bindFlagsLoadViper(cmd *cobra.Command, args []string) error {
// cmd.Flags() includes flags from this command and all persistent flags from the parent
if err := viper.BindPFlags(cmd.Flags()); err != nil {
return err
}
homeDir := viper.GetString(HomeFlag)
viper.Set(HomeFlag, homeDir)
viper.SetConfigName("config") // name of config file (without extension)
viper.AddConfigPath(homeDir) // search root directory
// If a config file is found, read it in.
if err := viper.ReadInConfig(); err == nil {
// stderr, so if we redirect output to json file, this doesn't appear
// fmt.Fprintln(os.Stderr, "Using config file:", viper.ConfigFileUsed())
} else if _, ok := err.(viper.ConfigFileNotFoundError); !ok {
// we ignore not found error, only parse error
// stderr, so if we redirect output to json file, this doesn't appear
fmt.Fprintf(os.Stderr, "%#v", err)
}
return nil
}
1 viper.SetConfigName 设置配置文件的名字
2 viper.AddConfigPath 设置配置文件的路径,为什么是add不是set呢,它的实现是append,就是它可以支持多目录搜索
3 viper.ReadInConfig 读取配置文件的内容然后放在viper.config内
只有path和名字就可以找到文件吗?后缀名呢?viper会查找一些内置支持的后缀
// SupportedExts are universally supported extensions.
var SupportedExts = []string{"json", "toml", "yaml", "yml", "properties", "props", "prop", "hcl"}
单个变量的读取比较简单,直接GetX(key)就行了,比如GetString,GetBool等
viper.GetString("encoding")
viper还支持结构体读取,比如Config结构体
func ParseConfig() (*UltronConfig, error) {
conf := DefaultConfig()
err := viper.Unmarshal(&conf)
if err != nil {
return nil, err
}
conf.TMConfig.SetRoot(conf.BaseConfig.RootDir)
ensureRoot(conf.BaseConfig.RootDir)
return conf, err
}
调用viper.Unmarshal(&conf)填充conf结构的内容
type P2PConfig struct {
RootDir string `mapstructure:"home"`
// Address to listen for incoming connections
ListenAddress string `mapstructure:"laddr"`
// Comma separated list of seed nodes to connect to
Seeds string `mapstructure:"seeds"`
// Skip UPNP port forwarding
SkipUPNP bool `mapstructure:"skip_upnp"`
// Path to address book
AddrBook string `mapstructure:"addr_book_file"`
// Set true for strict address routability rules
AddrBookStrict bool `mapstructure:"addr_book_strict"`
// Set true to enable the peer-exchange reactor
PexReactor bool `mapstructure:"pex"`
// Maximum number of peers to connect to
MaxNumPeers int `mapstructure:"max_num_peers"`
// Time to wait before flushing messages out on the connection, in ms
FlushThrottleTimeout int `mapstructure:"flush_throttle_timeout"`
// Maximum size of a message packet payload, in bytes
MaxMsgPacketPayloadSize int `mapstructure:"max_msg_packet_payload_size"`
// Rate at which packets can be sent, in bytes/second
SendRate int64 `mapstructure:"send_rate"`
// Rate at which packets can be received, in bytes/second
RecvRate int64 `mapstructure:"recv_rate"`
}
这个是config.toml中的p2p
[p2p]
laddr = "tcp://0.0.0.0:46656"
seeds = "172.29.18.158:46656"
两个是有对应关系的。在代码中需要写 'mapstructure:"seeds"',然后viper读取的时候会根据这个规则对应到具体的变量上