multierr في Go: دمج الأخطاء المتعددة والتعامل معها
في لغة Go، معالجة الأخطاء هي جزء أساسي وواضح من عملية التطوير. ولكن غالبًا ما تنشأ حالة قد يحدث فيها أكثر من خطأ واحد أثناء تنفيذ عملية واحدة. على سبيل المثال، عند معالجة مجموعة من الملفات، أو التحقق من صحة بنية بيانات معقدة، أو تنفيذ مهام متوازية. الحزمة القياسية errors تسمح بالعمل مع خطأ واحد فقط في كل مرة، مما يعقد عملية جمع وتحليل جميع الأخطاء التي حدثت.
مكتبة multierr من شركة Uber (نفس الشركة التي أنشأت zap و fx) تحل هذه المشكلة بأناقة وفعالية. توفر واجهة برمجية بسيطة لدمج عدة أخطاء مستقلة في خطأ واحد مركب (composite error). هذا يسمح بالاحتفاظ بسياق جميع الأخطاء دون فقدان المعلومات، ومعالجتها في مكان واحد. على عكس الإنشاء اليدوي لمصفوفات الأخطاء، تقدم multierr دوالًا مريحة للدمج والتحقق من وجود الأخطاء والتكرار عبرها.
الفلسفة الأساسية للمكتبة هي البساطة والأداء العالي. إنها لا تقوم بإنشاء تخصيصات غير ضرورية في الذاكرة (heap allocations) إذا لم تكن هناك حاجة لذلك، وتحاول تقليل التكاليف الإضافية. multierr مثالية للحالات التي تحتاج فيها إلى جمع الأخطاء من مصادر مختلفة (مثل الـ goroutines) وإرجاعها كنتيجة واحدة يمكن التحقق من وجود أخطاء فيها باستخدام if err != nil القياسي.
التثبيت
يتم تثبيت المكتبة باستخدام الأمر القياسي go get. تأكد من أن لديك إصدار Go 1.13 أو أحدث (لدعم errors.Is و errors.As).
go get go.uber.org/multierr
بعد تنفيذ الأمر، ستتم إضافة المكتبة إلى ملف go.mod الخاص بك. يتم استيرادها كالتالي:
import "go.uber.org/multierr"
بداية سريعة: مثال بسيط
لنلقِ نظرة على أبسط حالة: لدينا دالتان قد ترجعان خطأ. نريد تنفيذ كلتيهما، وإذا فشلت واحدة على الأقل، نعيد خطأً مشتركًا.
package main
import (
"errors"
"fmt"
"go.uber.org/multierr"
)
func doSomething() error {
return errors.New("الخطأ الأول")
}
func doAnotherThing() error {
return errors.New("الخطأ الثاني")
}
func main() {
var err error
// تنفيذ العملية الأولى
err = multierr.Append(err, doSomething())
// تنفيذ العملية الثانية
err = multierr.Append(err, doAnotherThing())
if err != nil {
fmt.Println("حدثت أخطاء:")
// طباعة جميع الأخطاء، كل خطأ في سطر منفصل
for _, e := range multierr.Errors(err) {
fmt.Println("-", e)
}
}
}
في هذا المثال، تقوم multierr.Append بإضافة خطأ جديد إلى الخطأ الموجود. إذا كان err يساوي nil، فإن الدالة ببساطة ترجع الخطأ الجديد. في النهاية، نحصل على خطأ مركب واحد يمكن تفكيكه إلى أجزاء باستخدام multierr.Errors.
الدوال والطرق الأساسية
توفر مكتبة multierr مجموعة صغيرة ولكنها قوية جدًا من الدوال. دعنا نستعرض كل منها بالتفصيل.
1. multierr.Append
التوقيع: func Append(left error, right error) error
الوصف: هذه هي الدالة الرئيسية لدمج خطأين. إذا كان كلا الخطأين يساويان nil، فسيتم إرجاع nil. إذا كان أحدهما nil، فسيتم إرجاع الآخر. إذا كان كلاهما ليس nil، فسيتم دمجهما في خطأ مركب واحد.
err1 := errors.New("خطأ 1")
err2 := e