العمل مع WebAssembly وGo: المستوى المتقدم
يفتح WebAssembly (WASM) آفاقًا جديدة لتطوير الويب، مما يسمح بتنفيذ كود عالي الأداء مكتوب بلغات غير JavaScript. تعتبر Go (Golang) مع مترجمها إلى WASM ونموذجها البسيط للتوازي مرشحًا ممتازًا لإنشاء وحدات ويب معقدة. في هذه المقالة، سنستعرض تقنيات متقدمة لتكامل Go وWebAssembly: العمل مع الذاكرة، تمرير هياكل البيانات المعقدة، الاتصال ثنائي الاتجاه مع JavaScript، وتحسين الأداء.
1. تمرير هياكل البيانات المعقدة بين Go وJavaScript
التمرير الأساسي للأرقام والسلاسل النصية عبر syscall/js بسيط، لكنه غير كافٍ للتطبيقات الحقيقية. النهج المتقدم يتضمن تسلسل الهياكل المعقدة (الشرائح، الخرائط، الأنواع المخصصة) إلى JSON أو تنسيق ثنائي.
التسلسل عبر JSON
الطريقة الأبسط والأكثر عمومية هي استخدام encoding/json. تقوم بتصدير دالة تستقبل سلسلة JSON، وتفك تسلسلها إلى هيكل Go، وتعالجها، وتعيد النتيجة على شكل JSON.
// main.gopackage main
import ( "encoding/json" "syscall/js")
type InputData struct { Name string `json:"name"` Value float64 `json:"value"`}
type OutputData struct { Greeting string `json:"greeting"` Square float64 `json:"square"`}
func processData(this js.Value, args []js.Value) interface{} { if len(args) < 1 { return "Error: expected JSON string" } inputJSON := args[0].String()
var input InputData if err := json.Unmarshal([]byte(inputJSON), &input); err != nil { return "Error: " + err.Error() }
output := OutputData{ Greeting: "Hello, " + input.Name, Square: input.Value * input.Value, }
resultJSON, _ := json.Marshal(output) return string(resultJSON)}
func main() { c := make(chan struct{}, 0) js.Global().Set("processData", js.FuncOf(processData)) <-c}العمل المباشر مع الذاكرة (البروتوكول الثنائي)
لأقصى أداء، يمكن تمرير البيانات عبر الذاكرة الخطية لـ WASM. تقوم بتصدير دوال للكتابة/القراءة من الذاكرة وتمرير المؤشرات (كأعداد صحيحة) إلى JavaScript. هذه الطريقة أكثر تعقيدًا، لكنها تتجنب التكاليف الإضافية لتحليل JSON.
// تصدير دالة للكتابة في الذاكرة//go:wasmexport allocateMemoryfunc allocateMemory(size int) uintptr { // نستخدم C.malloc أو مخصص الذاكرة الخاص بنا // نعيد المؤشر}
//go:wasmexport getMemoryBufferfunc getMemoryBuffer() uintptr { // نعيد بداية المخزن المؤقت}في JavaScript، تستخدم WebAssembly.Memory و Uint8Array للقراءة/الكتابة على العناوين المستلمة.
2. استدعاء JavaScript من Go والتحكم في DOM
تتيح حزمة syscall/js استدعاء أي دوال JavaScript والتلاعب بـ DOM. المستوى المتقدم يتضمن إنشاء واجهات تفاعلية ومعالجة الأحداث.
إنشاء وتحديث عناصر DOM
func appendDiv(this js.Value, args []js.Value) interface{} { document := js.Global().Get("document") body := document.Get("body")
newDiv := document.Call("createElement", "div") newDiv.Set("innerHTML", "<h2>Hello from Go WASM!</h2>") newDiv.Get("style").Set("color", "blue") body.Call("appendChild", newDiv) return nil}
func main() { js.Global().Set("appendDiv", js.FuncOf(appendDiv)) select {}}معالجة الأحداث من جانب Go
func setupClickHandler(this js.Value, args []js.Value) interface{} { document := js.Global().Get("document") button := document.Call("getElementById", "myButton")
clickCallback := js.FuncOf(func(this js.Value, args []js