本文的翻译是为“ 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 , (, , ). - . , , , .