لماذا Go ليس جزيرة، بل جسر
\n\nGo لغة رائعة. إنها سريعة، ومترجمة، ولها مكتبة قياسية ممتازة. لكن لنكن صادقين: في العالم الحقيقي، نادرًا ما نكتب كل شيء من الصفر بلغة واحدة. لديك مكتبة قديمة ومجربة على C يصعب إعادة كتابتها. أو سكريبت رائع على Python للتعلم الآلي. أو تريد تشغيل منطق Go مباشرة في المتصفح.
\nوهنا يطرح السؤال: كيف ندمج Go مع اللغات الأخرى؟ لا تقلق، تم تصميم Go ليكون "جارًا" جيدًا. في هذه المقالة على PythonLib، سنشرح ثلاث طرق رئيسية لجعل برنامج Go الخاص بك يتعاون مع كود الآخرين. ستتعلم كيف يعمل cgo، وكيفية استدعاء دوال Python عبر استدعاءات النظام، وحتى كيفية ترجمة Go إلى WebAssembly.
تكامل Go مع C عبر cgo: الكلاسيكي
\n\nالطريقة الأكثر مباشرة وقوة هي cgo. إنها ليست مكتبة، بل آلية مدمجة في Go تسمح لكودك باستدعاء دوال C مباشرة. كيف يعمل هذا؟ ببساطة تكتب استيراد "C" وقبله تعليق بكود C. مترجم Go سيقوم بدمج كل شيء.
كتابة أول برنامج باستخدام cgo
\n\nلنكتب مثالًا بسيطًا: استدعاء printf القياسية من C. أنشئ ملفًا باسم main.go:
package main\n\n/*\n#include <stdio.h>\n#include <stdlib.h>\n\nvoid hello_cgo(const char* name) {\n printf("مرحبًا من C، %s!\\n", name);\n}\n*/\nimport "C"\nimport "unsafe"\n\nfunc main() {\n name := C.CString("Gopher")\n defer C.free(unsafe.Pointer(name))\n C.hello_cgo(name)\n}\n\n\nشغّل: go run main.go. إذا كان لديك GCC (أو MinGW على Windows)، سيتم تجميع كل شيء. سترى «مرحبًا من C، Gopher!». سحر!
مهم: C.CString يخصص ذاكرة في كومة C، لذا يجب علينا تحريرها عبر C.free. وإلا سيحدث تسرب للذاكرة. يتطلب منك cgo الانضباط.
تمرير الأنواع المعقدة: الهياكل (Structs)
\n\nغالبًا ما نحتاج للعمل مع هياكل وليس نصوصًا. لنفترض أن لدينا مكتبة C للعمل مع المصفوفات. نريد تمرير هيكل Go إليها. لنفعل ذلك:
\n\npackage main\n\n/*\ntypedef struct {\n int x;\n int y;\n int result;\n} Point;\n\nPoint add_points(Point a, Point b) {\n Point r;\n r.x = a.x + b.x;\n r.y = a.y + b.y;\n r.result = r.x + r.y;\n return r;\n}\n*/\nimport "C"\nimport "fmt"\n\ntype GoPoint struct {\n X, Y, Result int\n}\n\nfunc main() {\n a := C.Point{x: 10, y: 20}\n b := C.Point{x: 30, y: 40}\n r := C.add_points(a, b)\n\n goPoint := GoPoint{\n X: int(r.x),\n Y: int(r.y),\n Result: int(r.result),\n }\n fmt.Printf("Go استلم: Point{X:%d, Y:%d, Result:%d}\\n", goPoint.X, goPoint.Y, goPoint.Result)\n}\n\n\nلاحظ: نقوم بتحويل أنواع C إلى أنواع Go بشكل صريح. لا يستطيع cgo تعيين الهياكل تلقائيًا، لذا أنت دائمًا مسؤول عن التحويل. هذا أحد التنازلات الرئيسية في تكامل Go مع لغة C.
\n\nمتى لا تحتاج إلى cgo
\nلا تستخدم cgo إذا:
\n- \n
- تحتاج فقط لاستدعاء أمر في الطرفية — استخدم
os/exec. \n - تكتب كودًا متعدد المنصات — cgo يعقد عملية البناء. \n
- الأداء ليس حرجًا — cgo يضيف تكاليف إضافية لتبديل السياق. \n
تكامل Go مع Python: البرمجة النصية بذكاء
\n\nPython و Go زوج رائع. Go للسرعة والتوازي، Python للمرونة والنظام البيئي (NumPy, TensorFlow). كيف نجعلهم يتعاونون؟ لدينا طريقتان: "ثقيلة" (عبر cgo و Python C API) و"خفيفة" (عبر العمليات الفرعية).
\n\nالطريقة 1: استدعاء Python عبر os/exec (بسيطة وموثوقة)
\n\nالطريقة الأكثر أمانًا لـ التعليم هي تشغيل سكريبت Python كعملية منفصلة