本文的翻译是为“ Golang开发人员。专业”课程的未来学生特别准备的。
选项是配置文件中存储的最常见的数据类型之一。在本文中,我将介绍在JSON中存储选项并在Go中取消编组时要考虑的一些事项。
特别是,期权和任何其他数据之间最重要的区别是,期权通常是可选的。我们的程序可以具有大量各种配置参数(选项),但是我们可能需要仅使用它们的有限子集来启动任何特定的调用,而其他所有参数都保留默认值。
基础知识-部分编组,省略和未知字段
让我们从基础开始。考虑以下结构,这是一个任意程序选项:
type Options struct {
Id string `json:"id,omitempty"`
Verbose bool `json:"verbose,omitempty"`
Level int `json:"level,omitempty"`
Power int `json:"power,omitempty"`
}该结构仅包含4个选项,但是在实际程序中可以有数十个选项。
假设我们要在JSON配置文件中指定这些选项。选项的完整列表可能如下所示:
{
"id": "foobar",
"verbose": false,
"level": 10,
"power": 221
}如果您的配置文件始终包含所有选项,则没有什么更多的要讨论的了。只需致电即可json.Unmarshal完成。
在实践中,它很少那么简单。我们需要立即处理几种特殊情况:
JSON配置中可能缺少一些字段,我们希望Go中的结构为其具有默认值。
JSON- , . , .
(1) json Go , JSON; Go. , JSON level, Options Level 0. , .
(2) json . , JSON:
{
"id": "foobar",
"bug": 42
}json.Unmarshal Options, Id "foobar", Level Power 0, Verbose false. bug.
, - . , json , JSON- DisallowUnknownFields:
dec := json.NewDecoder(bytes.NewReader(jsonText))
dec.DisallowUnknownFields()
var opts Options
if err := dec.Decode(&opts2); err != nil {
fmt.Println("Decode error:", err)
}JSON .
, , Options omitempty, . , JSON. :
opts := Options{
Id: "baz",
Level: 0,
}
out, _ := json.MarshalIndent(opts, "", " ")
fmt.Println(string(out)):
{
"id": "baz"
}. , omitempty.
, JSON- Go. , , . , Power 10, 0? , JSON «power», Power 10, Unmarshal .
- ! Power 10 , JSON 0! . , JSON 0?
, . , json.Unmarshal :
func parseOptions(jsn []byte) Options {
opts := Options{
Verbose: false,
Level: 0,
Power: 10,
}
if err := json.Unmarshal(jsn, &opts); err != nil {
log.Fatal(err)
}
return opts
} json.Unmarshal Options, parseOptions.
UnmarshalJSON Options:
func (o *Options) UnmarshalJSON(text []byte) error {
type options Options
opts := options{
Power: 10,
}
if err := json.Unmarshal(text, &opts); err != nil {
return err
}
*o = Options(opts)
return nil
} json.Unmarshal Options Power . options - UnmarshalJSON.
, . -, . , , ; .
, . Options , . :
type Region struct {
Name string `json:"name,omitempty"`
Power int `json:"power,omitempty"`
}
type Options struct {
Id string `json:"id,omitempty"`
Verbose bool `json:"verbose,omitempty"`
Level int `json:"level,omitempty"`
Power int `json:"power,omitempty"`
Regions []Region `json:"regions,omitempty"`
} Power Region, Options. Region. - UnmarshalJSON .
, . -.
-
Options :
type Options struct {
Id *string `json:"id,omitempty"`
Verbose *bool `json:"verbose,omitempty"`
Level *int `json:"level,omitempty"`
Power *int `json:"power,omitempty"`
}, , . , JSON:
{
"id": "foobar",
"verbose": false,
"level": 10
}, , "power". :
var opts Options
if err := json.Unmarshal(jsonText, &opts); err != nil {
log.Fatal(err)
} , ( nil ), , ( ). , Options :\
func parseOptions(jsn []byte) Options {
var opts Options
if err := json.Unmarshal(jsonText, &opts); err != nil {
log.Fatal(err)
}
if opts.Power == nil {
var v int = 10
opts.Power = &v
}
return opts
} , opts.Power; , Go , , int. , , :
func Bool(v bool) *bool { return &v }
func Int(v int) *int { return &v }
func String(v string) *string { return &v }
// .. ... , opts.Power = Int(10).
, , JSON. Options , , nil.
- « »? . , , , . Protobuf protobuf- proto2, . !
, . , , Go , (, , ). - . , , , .