خطأ "undefined" لدالة في Go: الأسباب والحلول | PythonLib

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

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

ابدأ الدورة

خطأ "Undefined" في Go: كيف تجعل الملفات تتعاون بسلاسة

\n\n

تخيل أنك تكتب برنامجًا بلغة Go، وتقسم الكود إلى ملفات منطقية (مثل main.go و helper.go)، ثم تشغل go run main.go — وفجأة يظهر لك المترجم رسالة باردة: «undefined: MyFunction». هل يبدو هذا مألوفًا؟ هذا السؤال هو من أكثر الأسئلة شيوعًا على Stack Overflow (آلاف المشاهدات!)، واليوم سنحل هذه المشكلة نهائيًا.

\n\n

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

\n\n

السيناريو 1: الكلاسيكي — نسيان تحديد جميع الملفات عند التشغيل

\n\n

الحالة الأكثر شيوعًا. تكتب:

\n\n
// main.go\npackage main\n\nfunc main() {\n    printHello() // خطأ: undefined: printHello\n}\n
\n\n
// helper.go\npackage main\n\nimport "fmt"\n\nfunc printHello() {\n    fmt.Println("مرحبًا!")\n}\n
\n\n

وتشغل فقط go run main.go. Go لا ترى helper.go لأنك لم تحددها صراحةً. الحل الصحيح:

\n\n
go run main.go helper.go\n// أو بشكل أبسط:\ngo run .\n
\n\n

لماذا يحدث هذا؟ Go لا تفحص المجلد تلقائيًا — يجب عليك سرد جميع ملفات الحزمة. الأمر go run . يشغل المجلد الحالي بأكمله كحزمة واحدة.

\n\n

السيناريو 2: حزم مختلفة — عدم الرؤية الافتراضية

\n\n

فخ شائع آخر هو محاولة استدعاء دالة من حزمة أخرى دون استيراد وتصدير.

\n\n
// main.go\npackage main\n\nfunc main() {\n    helper.DoSomething() // خطأ: undefined: helper\n}\n
\n\n
// helper/helper.go\npackage helper\n\nfunc DoSomething() {\n    // ...\n}\n
\n\n

هنا مشكلتان:

\n
    \n
  • الملفات في حزم مختلفة (main و helper).
  • \n
  • الدالة DoSomething غير مُصدّرة (تبدأ بحرف صغير).
  • \n
\n\n

النسخة المصححة:

\n\n
// main.go\npackage main\n\nimport "yourmodule/helper"\n\nfunc main() {\n    helper.DoSomething() // يعمل!\n}\n
\n\n
// helper/helper.go\npackage helper\n\nfunc DoSomething() { // حرف كبير!\n    // ...\n}\n
\n\n

تذكر: في Go، يتم تصدير الكيانات التي تبدأ بـ حرف كبير فقط. الحرف الصغير يعني أنها خاصة بالحزمة.

\n\n

السيناريو 3: مشاكل مع الوحدات و GOPATH

\n\n

إذا كنت تستخدم النمط القديم (GOPATH) أو قمت بتهيئة الوحدة بشكل غير صحيح، فقد لا تجد Go ملفاتك حتى في نفس المجلد.

\n\n

تحقق من:

\n
    \n
  1. هل يوجد ملف go.mod في جذر المشروع؟ إذا لم يكن موجودًا، أنشئه: go mod init اسم_الوحدة.
  2. \n
  3. هل تخزن المشروع داخل $GOPATH/src بدون وحدة؟ هذا وضع قديم قد يسبب ارتباكًا.
  4. \n
  5. تأكد من أن جميع الملفات في المجلد لها نفس package (باستثناء ملفات الاختبار التي تنتهي بـ _test).
  6. \n
\n\n

مثال على هيكل صحيح:

\n\n
myproject/\n├── go.mod          # module myproject\n├── main.go         # package main\n└── helper.go       # package main\n
\n\n

السيناريو 4: أسماء الملفات ذات الشرطات السفلية وملفات الاختبار

\n\n

Go تتجاهل الملفات التي تبدأ بـ _ أو . (مثل _hidden.go). أما الملفات التي تنتهي بـ _test.go فتُجمّع فقط عند تشغيل الاختبارات (go test). إذا سمّيت ملف العمل عن طريق الخطأ helper_test.go — فلن تظهر دوالّه في الكود الرئيسي.

\n\n

السيناريو 5: التبعيات الدائرية

\n\n

أحيانًا، قد يكون خطأ "undefined" نتيجة لاستيراد دائري. على سبيل المثال، الحزمة A تستورد B، و B تستورد A. Go تمنع هذه الحلقات وقد تظهر أخطاء غريبة. الحل هو إعادة هيكلة الكود لكسر الدائرة.

المدونات

توصيات الكتب