لماذا Go و WebSockets هما الثنائي المثالي للتطبيقات الفورية؟
تخيل موقفًا: تقوم بتشغيل دردشة عبر الإنترنت، أو محطة تداول، أو لعبة متعددة اللاعبين. المستخدمون ينتظرون ردًا فوريًا. لا أحد يريد تحديث الصفحة يدويًا أو الانتظار 5 ثوانٍ حتى يأتي الرد من الخادم. هنا يظهر WebSockets على المسرح.
Go (Golang) مناسبة تمامًا لهذه المهمة. تسمح goroutines خفيفة الوزن بالحفاظ على عشرات الآلاف من الاتصالات المتزامنة دون انخفاض في الأداء. والمكتبة القياسية net/http مع حزمة gorilla/websocket تجعل كتابة التطبيقات الفورية متعة خالصة.
في هذه المقالة، سنفهم كيفية عمل WebSocket في Go، ونكتب دردشة بسيطة، ونناقش أفضل الممارسات. هيا بنا!
ما هو WebSocket وكيف يختلف عن HTTP؟
باختصار - WebSocket هو بروتوكول ينشئ اتصالًا ثنائي الاتجاه دائمًا بين العميل (المتصفح) والخادم. على عكس HTTP التقليدي، حيث يبدأ العميل دائمًا الطلب، يسمح WebSocket للخادم بإرسال البيانات إلى العميل في أي وقت.
المزايا واضحة:
- توصيل فوري - لا تأخير في إنشاء اتصال جديد.
- حركة مرور أقل - يتم إرسال الرؤوس مرة واحدة فقط عند المصافحة.
- كفاءة - اتصال واحد بدلاً من آلاف طلبات HTTP.
تتعامل Go بشكل ممتاز مع إدارة هذه الاتصالات. بدلاً من إنشاء خيوط نظام التشغيل (وهو مكلف)، تستخدم Go goroutines. goroutine واحدة - اتصال واحد. آلاف goroutines تعمل على عدة خيوط نظام تشغيل، وتستهلك حدًا أدنى من الذاكرة.
تثبيت وإعداد مشروع Go
لنفترض أن Go مثبت لديك بالفعل. إذا لم يكن كذلك - brew install go أو قم بالتنزيل من golang.org.
لننشئ وحدة جديدة:
mkdir go-websocket-chatcd go-websocket-chatgo mod init go-websocket-chatالآن لنقم بتثبيت المكتبة الأكثر شيوعًا gorilla/websocket:
go get github.com/gorilla/websocketجاهز. الآن لدينا كل شيء لإنشاء تطبيق فوري على Go.
كتابة خادم WebSocket على Go
لنبدأ بأبسط شيء - خادم الصدى. يرسل العميل رسالة، ويعيدها الخادم. سيساعدنا هذا في فهم الآلية الأساسية.
الخطوة 1: الهيكل وترقية الاتصال
يبدأ اتصال WebSocket بطلب HTTP (مصافحة). يجب على الخادم "ترقية" هذا الاتصال إلى WebSocket. في Go، يتم ذلك عبر http.Hijacker أو عبر الطريقة المريحة Upgrader من حزمة gorilla/websocket.
قم بإنشاء ملف main.go:
package main
import ( "fmt" "log" "net/http" "github.com/gorilla/websocket")
var upgrader = websocket.Upgrader{ CheckOrigin: func(r *http.Request) bool { return true // السماح بأي مصادر (للتطوير) },}
func handleWebSocket(w http.ResponseWriter, r *http.Request) { conn, err := upgrader.Upgrade(w, r, nil) if err != nil { log.Print("خطأ في الترقية:", err) return } defer conn.Close()
// حلقة لا نهائية للقراءة والكتابة for { messageType, message, err := conn.ReadMessage() if err != nil { log.Println("خطأ في القراءة:", err) break } log.Printf("تم الاستلام: %s", message)
// إعادة إرسال نفس الشيء err = conn.WriteMessage(messageType, message) if err != nil { log.Println("خطأ في الكتابة:", err) break } }}
func main() { http.HandleFunc("/ws", handleWebSocket) fmt.Println("الخادم يعمل على :8080") log.Fatal(http.ListenAndServe(":8080", nil))}قم بتشغيله: go run main.go