وظائف Serverless بلغة Go: AWS Lambda — دليل شامل
تستمر بنية Serverless في اكتساب شعبية بين المطورين بفضل قابليتها للتوسع، وتقليل التكاليف التشغيلية، وعدم الحاجة إلى إدارة الخوادم. AWS Lambda هي إحدى الشركات الرائدة في هذا المجال. ماذا لو جمعنا قوة serverless مع أداء وبساطة Go (Golang)؟ في هذه المقالة، سنشرح كيفية إنشاء وتكوين ونشر وظائف serverless بلغة Go لـ AWS Lambda. ستتعرف على مزايا هذا النهج، وتكتب أول وظيفة لك، وتحصل على نصائح عملية للتحسين.
لماذا تعتبر Go (Golang) مثالية لـ AWS Lambda؟
اختيار لغة البرمجة لوظائف serverless أمر بالغ الأهمية. تمتلك Go (Golang) مجموعة من المزايا الفريدة التي تجعلها واحدة من أفضل الخيارات للعمل مع AWS Lambda:
- بداية باردة سريعة: على عكس اللغات المفسرة (Python, Node.js)، يتم تجميع Go إلى ملف ثنائي أصلي. وقت التشغيل (cold start) يُقاس بالمللي ثانية، وهو أمر بالغ الأهمية لـ API والخدمات المصغرة.
- استهلاك منخفض للذاكرة: تطبيقات Go خفيفة الوزن وتستخدم الذاكرة بكفاءة، مما يؤثر بشكل مباشر على تكلفة تنفيذ الوظائف (أنت تدفع مقابل الذاكرة المخصصة).
- سهولة النشر: تقوم بتجميع ملف ثنائي واحد، وتحميله إلى AWS Lambda، ويعمل دون أي تبعيات خارجية (باستثناء المكتبة القياسية). لا توجد بيئات افتراضية أو node_modules.
- أداء عالٍ: Go هي لغة مُجمّعة مع دعم مدمج للتوافقية (goroutines). هذا يسمح بمعالجة آلاف الطلبات داخل وظيفة Lambda واحدة دون أعباء كبيرة.
- تكامل ممتاز مع AWS SDK: يوفر AWS SDK الرسمي لـ Go (v2) عملاء ملائمين ومكتوبين بشكل نموذجي لجميع خدمات AWS.
إنشاء أول وظيفة Serverless بلغة Go لـ AWS Lambda
لنكتب وظيفة بسيطة تعالج طلب HTTP عبر AWS Lambda Function URL أو API Gateway. للقيام بذلك، سنحتاج إلى الحزمة github.com/aws/aws-lambda-go.
الخطوة 1: تهيئة المشروع وتثبيت التبعيات
mkdir my-lambda-gocd my-lambda-gogo mod init my-lambda-gogo get github.com/aws/aws-lambda-go/lambdago get github.com/aws/aws-lambda-go/eventsالخطوة 2: كود الوظيفة (main.go)
ستستقبل هذه الوظيفة طلب JSON باسم المستخدم وتُرجع تحية.
package main
import (\t"context"\t"encoding/json"\t"fmt"\t"log"
\t"github.com/aws/aws-lambda-go/events"\t"github.com/aws/aws-lambda-go/lambda")
// Request هيكل للطلب الواردtype Request struct {\tName string `json:"name"`}
// Response هيكل للردtype Response struct {\tMessage string `json:"message"`}
func handleRequest(ctx context.Context, request events.APIGatewayProxyRequest) (events.APIGatewayProxyResponse, error) {\tvar req Request
\t// نوزع جسم الطلب\tif err := json.Unmarshal([]byte(request.Body), &req); err != nil {\t\tlog.Printf("Error parsing request: %v", err)\t\treturn events.APIGatewayProxyResponse{\t\t\tStatusCode: 400,\t\t\tBody: `{"error":"Invalid JSON"}`,\t\t\tHeaders: map[string]string{"Content-Type": "application/json"},\t\t}, nil\t}
\t// نشكل الرد\tmessage := fmt.Sprintf("Hello, %s! Welcome to Serverless Go.", req.Name)\tresp := Response{Message: message}
\tjsonResp, _ := json.Marshal(resp)
\treturn events.APIGatewayProxyResponse{\t\tStatusCode: 200,\t\tBody: string(jsonResp),\t\tHeaders: map[string]string{"Content-Type": "application/json"},\t}, nil}
func mai