La traducción del artículo fue preparada especialmente para futuros alumnos del curso "Golang Developer. Professional" .
Uno de los tipos de datos más comunes almacenados en archivos de configuración son las opciones . En este artículo, cubriré algunos de los matices a considerar al almacenar opciones en JSON y desagruparlas en Go.
En particular, la diferencia más importante entre las opciones y cualquier otro dato es que las opciones son a menudo, perdón el juego de palabras ... opcionales . Nuestro programa puede tener una gran cantidad de todo tipo de parámetros de configuración (opciones), pero es posible que necesitemos iniciar cualquier invocación específica con solo un subconjunto limitado de ellos, dejando los valores predeterminados para todo lo demás.
Conceptos básicos: campos anómalos parciales, omniscientes y desconocidos
. , :
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 , (, , ). - . , , , .