当加载配置的时候,我们通常会将配置设置一个默认值,但是通常默认值不是Go中的空值,比如 服务的端口号:
type ServerConfig struct{
Port uint
}
func main(){
conf:=loadConfig()
if conf.ServerConfig.Port==0{
conf.ServerConfig.Port = 8080
}
}
每次有一个值我们都需要增加一个if语句进行判断,当一个配置有很多的时候,初始化写起来可能就非常的繁琐。
tag
原理比较简单大概流程就是:
- 通过反射解析当前的结构体
- 查看当前字段的值时候为空值
- 如果为空,读取tag中的default,并初始化
- 不为空直接略过
这里给出使用方法:
Defaults
Enforce default values on struct fields.
type User struct {
Name string `default:"Goku"`
Power float64 `default:"9000.01"`
}
var u User
err := defaults.Apply(&u)
if err != nil {
log.Fatal("Uh oh: %v", err)
}
fmt.Print(u.Name) // Goku
fmt.Print(u.Power) // 9000.01
Defaults are only applied to fields at their zero value.
type Config struct {
Host *string `default:"0.0.0.0"`
Port *int `default:"8000"`
}
var cfg Config
json.Unmarshal([]byte(`{Host: "charm.sh"}`), &cfg)
if err := defaults.Apply(&cfg); err != nil {
log.Fatal("Rats: %v", err)
}
fmt.Print(cfg.Host) // charm.sh
fmt.Print(cfg.Port) // 8000
Works well with JSON, Yaml, and so on.
type Config struct {
Host string `json:"host" default:"0.0.0.0"`
Port int `json:"port" default:"8000"`
Debug bool `json:"debug" default:"true"`
}
Supported Types
The following types are supported:
stringboolintint8int16int32runeint64uintuint8uint16uint32uint64float32float64[]byte[]uint8
…as well as pointers to those types.
Embedded Structs
Embedded structs are supported. The following will parse as expected:
type GroceryList struct {
Fruit struct {
Bananas int `default:"8"`
Pears int `default:"12"`
}
Vegetables *struct {
Artichokes int `default:"4"`
SweetPotatoes int `default:"16"`
}
}
defaultnil
Runes and Int32s
runeint32"1"1'1'int3249
runeint32rune
// This works as expected...
type Cool struct {
Fave32BitInteger int32 `default:"12"`
FaveChar rune `default:"a"`
}
// ...but these will not.
type UhOh struct {
FaveChar rune `default:"3"` // this is a unicode ETX or ctrl+c
FaveChar rune `default:"97"` // this is a unicode `a`
}
这个package本来是: github.com/charmbracelet/defaults 但是原地址无法访问