\ عندما بدأت تعلم Go، كان أحد أول الأسئلة التي طرحتها هو:
"كيف أقوم فعلياً بهيكلة الكود الخاص بي؟"
في لغات مثل C، من الشائع وضع كل شيء في ملف واحد، أو ربما فصل ملفات الرأس والتنفيذ. لكن في Go، هيكل المشروع أمر مهم: فهو يؤثر على مدى سهولة توسيع واختبار ومشاركة الكود الخاص بك. في هذا المقال، سأشرح سبب أهمية الهيكلة، وكيفية الوصول إلى الدوال من ملفات مختلفة، وأفضل الممارسات التي أتعلمها أثناء تقدمي.
يمكن أن يعيش برنامج Go بالكامل في ملف واحد:
package main import "fmt" func main() { fmt.Println("2 + 2 =", 2+2) }
هذا يعمل بشكل جيد لـ "hello world" أو التجارب السريعة.
ولكن بمجرد إضافة المزيد من الوظائف (الطرح، الضرب، القسمة...)، يصبح الملف فوضوياً وبالكاد قابلاً للتوسع.
هنا يأتي دور الحزم و المجلدات في Go.
في Go، كل ملف ينتمي إلى حزمة.
حسب الاتفاقية:
إليك كيف قمت بتقسيم مشروع الآلة الحاسبة:
calculator/ │ ├── main.go └── calculator/ └── operations.go
\
package calculator func Add(a, b int) int { return a + b } func Subtract(a, b int) int { return a - b } func Multiply(a, b int) int { return a * b } func Divide(a, b int) (int, error) { if b == 0 { return 0, fmt.Errorf("cannot divide by zero") } return a / b, nil }
package main import ( "fmt" "GoLang-progress/calculator" ) func main() { fmt.Println("2 + 3 =", calculator.Add(2, 3)) fmt.Println("10 - 4 =", calculator.Subtract(10, 4)) fmt.Println("6 * 7 =", calculator.Multiply(6, 7)) result, err := calculator.Divide(8, 0) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("8 / 0 =", result) } }
لاحظ كيف أن main.go أصبح الآن نظيفاً: فهو لا يقلق بشأن الرياضيات نفسها، بل فقط كيفية استخدامها.
سؤال شائع للمبتدئين:
"كيف أستدعي دالة من ملف أو مجلد آخر؟"
في المستودع الخاص بي، قمت بهيكلته بهذه الطريقة:
calculator/ │ ├── main.go └── internal/ └── calc/ └── operations.go
هنا، توجد دوال الرياضيات تحت internal/calc.
\
package calc import "fmt" func Add(a, b int) int { return a + b } func Divide(a, b int) (int, error) { if b == 0 { return 0, fmt.Errorf("cannot divide by zero") } return a / b, nil }
\
package main import ( "fmt" "github.com/turman17/GoLang-progress/calculator/internal/calc" ) func main() { fmt.Println("2 + 3 =", calc.Add(2, 3)) result, err := calc.Divide(10, 0) if err != nil { fmt.Println("Error:", err) } else { fmt.Println("10 / 2 =", result) } }
يجب أن يتطابق الاستيراد الخاص بك مع مسار الوحدة من go.mod بالإضافة إلى مسار المجلد.
في المستودع الخاص بك، يحتوي go.mod على:
module github.com/turman17/GoLang-progress
كود الآلة الحاسبة الذي تريد استخدامه موجود في المجلد:
calculator/internal/calc
لذا فإن مسار الاستيراد الكامل هو:
github.com/turman17/GoLang-progress/calculator/internal/calc
الأخطاء الشائعة والإصلاحات
❌ import "GoLang-progress/calculator/internal/calc"
→ اسم مؤسسة/مستخدم GitHub مفقود. يجب استخدام المسار الكامل.
❌ import "github.com/turman17/GoLang-progress/internal/calc"
→ دليل calculator مفقود في المسار.
❌ go: module not found errors
→ تأكد من أن go.mod يحتوي على module github.com/turman17/GoLang-progress وقم بتشغيل go mod tidy.
\
go run ./calculator
أو
go build ./calculator
مع نمو المشاريع، غالباً ما سترى هذا النمط:
project-name/ │ ├── cmd/ → executables (main entrypoints) ├── internal/ → private code (not for external use) ├── pkg/ → reusable packages ├── api/ → API definitions (gRPC, OpenAPI, etc.) └── go.mod
بالنسبة للمبتدئين، قد يكون هذا مبالغاً فيه. ولكن عندما تنتقل إلى تطبيقات الويب أو الخدمات أو أدوات MLOps، يصبح هذا التخطيط ضرورياً.
سأواصل مشاركة ما أتعلمه أثناء استكشافي لـ Go من أجل MLOps وتطوير الواجهة الخلفية. القادم: معالجة الأخطاء والاختبار في Go.
\ 👉 تحقق من المستودع الخاص بي هنا: https://github.com/turman17/GoLang-progress
وترقبوا المقال القادم!