تم إعداد ترجمة المقال خصيصًا للطلاب المستقبليين لدورة "Golang Developer. Professional" .
تعد الخيارات من أكثر أنواع البيانات المخزنة في ملفات التكوين شيوعًا . في هذه المقالة ، سأغطي بعض الفروق الدقيقة التي يجب مراعاتها عند تخزين الخيارات في 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 , (, , ). - . , , , .