لا شيء ليس دائمًا
"ماذا؟ ما هو مكتوب هنا؟" أنت تسأل. الآن سأضع كل ذلك.
عندما بدأت في تعلم اللغة ، لم أكن أعتقد أنني سأصل إلى هذه الحالة الضيقة. كما أنه ليس من المنطقي تعديل مجموعة قابلة للتكرار.
على سبيل المثال:
func Foo() error { var err *os.PathError = nil return err } func main() { err := Foo() fmt.Println(err) // <nil> fmt.Println(err == nil) // false }
WAT!
ما هي الواجهة؟
انتقل إلى ملف حزمة go runtime / runtime2.go وانظر:
type itab struct { // 40 bytes on a 64bit arch inter *interfacetype _type *_type ... }
تخزن الواجهة نوع الواجهة ونوع القيمة نفسها.
قيمة أي واجهة ، وليس مجرد خطأ ، هي الصفر في الحالة التي تكون فيها قيم AND ونوعًا لا شيء.
تقوم دالة Foo بإرجاع nil of type * os.PathError ، حيث نقارن النتيجة مع nil of type nil ، والتي يتبعها عدم المساواة.
ربما يعلم الكثير عن هذا ، لكن قلة من الناس يفكرون في كيفية الدخول إليه في الممارسة العملية.
مثالي
type Response struct { Result ResponseResult `json:"result,omitempty"` Error *ResponseError `json:"error,omitempty"` } type ResponseError struct { Message string `json:"message"` } func (e *ResponseError) Error() string { return e.Message } ... func (s *NotificationService) NotifyIfError(w *ResponseWriter) error { ... var res handlers.Response _ = json.Unmarshal(body, &res) if res.Error == nil { return } return s.NotifyError(err) }
استجابة دائما نتيجة أو خطأ.
إذا كان هناك خطأ ، فنحن نرسله عند الضرورة من خلال خدمة الإعلام.
داخل الخدمة ، تسمى طريقة الخطأ ، وبما أن قيمتنا لا شيء ، فنحن نشعر بالذعر.
ما يجب القيام به
إرجاع واجهة بدقة من نوع الواجهة.
في حالة وجود خطأ - نوع الخطأ.
func (s *NotificationService) NotifyIfError(w *ResponseWriter) error { ... var res Response _ = json.Unmarshal(body, &res) var err error = res.Error return s.NotifyError(err) }
هذه التقنية ، لدهشتي ، لا تعمل أيضا.
اتضح أنه عند تعيين قيمة لمتغير err ، فإننا نقوم أيضًا بتمرير المعلومات الأولية الخاصة بالنوع ، والتي ليست خالية.
- دعونا نحاول الحصول على نوع مصدرنا من نوع الواجهة والتحقق من قيمته.
func (s *NotificationService) NotifyIfError(w *ResponseWriter) error { ... if e, ok := err.(*ResponseError); ok && e == nil { return s.NotifyError(err) } return nil }
نعم ، هذه التقنية تعمل.
ولكن بصراحة ، لا يمكننا أن نتحقق من جميع أنواع الأخطاء التي سنرسلها.
يمكن أن يكون كل الأخطاء من برنامج تشغيل قاعدة البيانات ، وجميع الأخطاء الداخلية لدينا وغيرها من القمامة.
ما هو الخيار الأكثر عقلانية الذي أراه:
func (s *NotificationService) NotifyIfError(w *ResponseWriter) error { var err error ... var res Response _ = json.Unmarshal(body, &res) if res.Error != nil { return s.NotifyError(err) } return nil }
أولاً ، أعلنا عن متغير خطأ في الكتابة ، حيث ظهر مع القيمة ونوع لا شيء.
وقبل تمرير نوعنا وقيمته إلى هذا المتغير ، دعونا نتحقق من نوعنا وقيمته على الصفر.
هذا سوف يسمح لنا بعدم الوقوع في حالة من الذعر.
في النهاية
يمكنك أن تذهب أبعد من ذلك وتنفذ خطأ "اختياري" بنوع الاستجابة أو اختياريالخطأ أو ErrorOrNil ، مثل هذا:
func (r *Response) ErrorOrNil() error { if r.Error == nil { return nil } return r.Error }
مذكرة
في ملاحظات Go wiki ، مراجعة الكود هي ملاحظة في موضوع حول الواجهة: بدلاً من ذلك ، قم بإرجاع نوع ملموس ودع المستهلك يسخر من تنفيذ المنتج.
وألاحظ أن الرقصات المذكورة أعلاه ليست حول هذا الموضوع.
تسمح لك ملاحظاتي بعدم الذعر عندما تعلم أنك تريد رد الاهتمام ، وفي حالة وجود أخطاء ، فأنت تريد دائمًا إرجاع الواجهة.
ولكن إذا كنت تستطيع إرجاع نوع معين ، فقم بإعادته.
مراجع
الداخلية-ذهاب
أنا كذلك
ينكدين
برقية
تغريد
جيثب