تصحيح أخطاء كود Go: من المبتدئ إلى المحترف في أمسية واحدة

مدرب بايثون أونلاين للمبتدئين

تعلم Python بسهولة دون إرهاق نظري. حل مهام عملية مع التحقق التلقائي واكتب الكود مباشرة في المتصفح.

ابدأ الدورة

لماذا يتعطل كود Go الخاص بك، وكيف تصلحه دون صداع

\n\n

لقد كتبت كودًا مثاليًا في Go حسب رأيك. مرت عملية التجميع بنجاح، والاختبارات خضراء... ولكن في الإنتاج ينهار كل شيء. مألوف؟ مرحبًا بك في عالم التطوير الحقيقي، حيث الأخطاء ليست أخطاء المبتدئين، بل جزء من النمو المهني. اليوم سنتناول تصحيح أخطاء كود Go بحيث لا تجد الأخطاء فحسب، بل تمنع ظهورها في مرحلة الكتابة.

\n\n

Go هي لغة تمنح المطور أدوات قوية لتصحيح الأخطاء مباشرة "من الصندوق". لكن الكثيرين يستخدمون فقط fmt.Println ويتساءلون بصدق لماذا تتصرف goroutines الخاصة بهم مثل القطط على سطح ساخن. دعنا نصلح هذا مرة واحدة وإلى الأبد.

\n\n

التقنية رقم 1: Print ذكي - عندما لا تحتاج إلى log.Fatal

\n\n

نعم، أعرف ما ستقوله: "لماذا أحتاج delve بينما يمكنني طباعة المتغير؟" وستكون محقًا في 80% من الحالات. لكن المشكلة ليست في fmt.Println، بل في كيفية استخدامك له.

\n\n

الانتقال من Println إلى التسجيل المنظم (structured logging)

\n\n

بدلاً من لصق عشرات الأوامر الطباعية، استخدم الحزمة log أو slog (المتاحة منذ Go 1.21):

\n\n
package main\n\nimport (\n    "log/slog"\n    "os"\n)\n\nfunc main() {\n    logger := slog.New(slog.NewTextHandler(os.Stdout, nil))\n    \n    // بدلاً من fmt.Println("خطأ:", err)\n    if err := doSomething(); err != nil {\n        logger.Error("فشلت العملية", \n            "error", err,\n            "module", "data_processor",\n            "attempt", 3,\n        )\n    }\n}\n
\n\n

هذا الأسلوب يمنحك سجلات منظمة يسهل تحليلها وتصفيتها وفحصها. في الإنتاج، سينقذك هذا من المكالمات الليلية.

\n\n

حيلة: الترجمة الشرطية لسجلات التصحيح

\n\n

لتجنب إرباك الإنتاج، استخدم build tags:

\n\n
//go:build debug\n\npackage main\n\nvar debug = true\n
\n\n
//go:build !debug\n\npackage main\n\nvar debug = false\n
\n\n

تشغيل مع العلم -tags debug - تحصل على سجلات مفصلة. بدون العلم - إنتاج نظيف.

\n\n

التقنية رقم 2: Delve - محققك الشخصي لـ Go

\n\n

إذا كان تصحيح الأخطاء بالطباعة هو دراجة هوائية، فإن Delve هو Tesla. هذا المصحح مصمم خصيصًا لـ Go ويفهم goroutines والواجهات وحتى generics. التثبيت بسيط:

\n\n
go install github.com/go-delve/delve/cmd/dlv@latest\n
\n\n

نقاط توقف تفكر

\n\n

يتيح لك Delve وضع ليس فقط breakpoint، بل نقاط شرطية:

\n\n
(dlv) break main.go:25 if userID == 42\n(dlv) continue\n
\n\n

سيتوقف المصحح فقط عندما يكون userID يساوي 42. تخيل كم من الوقت يوفر هذا عند تصحيح أخطاء الحلقات.

\n\n

استكشاف goroutines

\n\n

أكثر ما يخيف في Go هو deadlock و race condition. يعرض Delve جميع goroutines النشطة:

\n\n
(dlv) goroutines\n  Goroutine 1 - User: ./main.go:10 main.main (0x109a5b6)\n  Goroutine 2 - User: ./main.go:15 main.worker (0x109a6c8)\n* Goroutine 3 - User: ./main.go:22 main.worker (0x109a6c8)\n
\n\n

النجمة تشير إلى goroutine الحالية. تنقل بينها:

\n\n
(dlv) goroutine 2\n(dlv) stack\n
\n\n

العمل مع الذاكرة: نرى ما بالداخل

\n\n

الأمر locals يعرض جميع المتغيرات المحلية، و print يطبع قيمها مع الأنواع:

\n\n
(dlv) locals\ndata = []int len: 100000, cap: 100000\nresult = map[string]int ["error": 5, "success": 99995]\n(dlv) print data[0:5]\n[]int len: 5, cap: 100000, [42, 17, 89, 3, 256]\n
\n\n

التقنية رقم 3: التنميط باستخدام pprof - نجد نقاط الضعف

\n\n

كودك يعمل لكنه بطيء؟ pprof هو ملف تعريف الأداء المدمج في Go. سيظهر أين "يتباطأ" البرنامج وأين يستهلك الذاكرة.

\n\n

إضافة نقطة نهاية HTTP

المدونات

توصيات الكتب