परिचय: उन्नत स्तर पर Go और WebAssembly क्यों?
\n\nWebAssembly (Wasm) एक प्रायोगिक तकनीक से उच्च-प्रदर्शन वाले वेब अनुप्रयोगों के लिए एक मानक बन गया है। Go, अपने कुशल संकलन और Wasm के लिए अंतर्निहित समर्थन के साथ, ब्राउज़र की सीमाओं पर काम करने वाले मॉड्यूल बनाने के लिए सबसे अच्छी भाषाओं में से एक है। बुनियादी "Hello, World!" उदाहरण अब प्रासंगिक नहीं हैं — आधुनिक कार्यों के लिए मेमोरी के सटीक प्रबंधन, जावास्क्रिप्ट के साथ दो-तरफा डेटा आदान-प्रदान और बाइनरी फ़ाइल आकार के अनुकूलन की आवश्यकता होती है।
\n\nइस लेख में, हम Go पर WebAssembly के साथ काम करने की उन्नत तकनीकों पर चर्चा करेंगे। आप सीखेंगे कि जटिल डेटा संरचनाओं को कैसे स्थानांतरित किया जाए, Go फ़ंक्शन को JavaScript से कैसे कॉल किया जाए और इसके विपरीत, और अपने Wasm मॉड्यूल के प्रदर्शन को कैसे अनुकूलित किया जाए। यह सामग्री उन डेवलपर्स के लिए है जो पहले से ही Go की मूल बातों से परिचित हैं और अपने कौशल को अगले स्तर पर ले जाना चाहते हैं।
\n\n1. मेमोरी प्रबंधन: स्ट्रिंग्स, ऐरे और स्ट्रक्चर का स्थानांतरण
\n\nWebAssembly के साथ काम करते समय मुख्य चुनौतियों में से एक Wasm की रैखिक मेमोरी और JavaScript के हीप के बीच जटिल डेटा का स्थानांतरण है। Go अपने स्वयं के गार्बेज कलेक्टर का उपयोग करता है, जो सीमाएँ लगाता है। आइए उन्नत विधियों पर विचार करें।
\n\n1.1. `copyBytesToGo` और `copyBytesToJS` के माध्यम से स्ट्रिंग्स की प्रतिलिपि
\n\nफ़ंक्शन पैरामीटर के माध्यम से सीधे स्ट्रिंग स्थानांतरण बड़े डेटा वॉल्यूम के लिए अक्षम है। इसके बजाय, syscall/js पैकेज के तरीकों का उपयोग करें:
package main\n\nimport (\n "syscall/js"\n "unsafe"\n)\n\n//export processLargeString\nfunc processLargeString(this js.Value, args []js.Value) interface{} {\n if len(args) < 1 {\n return nil\n }\n jsStr := args[0]\n // स्ट्रिंग की लंबाई प्राप्त करें\n length := jsStr.Get("length").Int()\n // Go मेमोरी में बफर बनाएँ\n buf := make([]byte, length)\n // JS से Go में डेटा कॉपी करें\n js.CopyBytesToGo(buf, jsStr)\n // अब buf में स्ट्रिंग के UTF-8 बाइट्स हैं\n // ... प्रसंस्करण ...\n // परिणाम वापस भेजें\n result := []byte("उत्तर: " + string(buf))\n dst := js.Global().Get("Uint8Array").New(len(result))\n js.CopyBytesToJS(dst, result)\n return dst\n}\n\nfunc main() {\n c := make(chan struct{}, 0)\n js.Global().Set("processLargeString", js.FuncOf(processLargeString))\n <-c\n}\n\n\n1.2. JSON-सीरियलाइज़ेशन के माध्यम से स्ट्रक्चर का स्थानांतरण
\n\nजटिल नेस्टेड संरचनाओं के लिए, मध्यवर्ती प्रारूप के रूप में JSON का उपयोग करें। यह सीधे मेमोरी के साथ काम करने की तुलना में धीमा है, लेकिन काफी अधिक सुविधाजनक है:
\n\n//export processUserData\nfunc processUserData(this js.Value, args []js.Value) interface{} {\n if len(args) < 1 {\n return js.ValueOf(map[string]interface{}{"error": "कोई डेटा नहीं"})\n }\n // JS से JSON-स्ट्रिंग प्राप्त करें\n jsonStr := args[0].String()\n var user User\n if err := json.Unmarshal([]byte(jsonStr), &user); err != nil {\n return js.ValueOf(map[string]interface{}{"error": err.Error()})\n }\n // डेटा प्रसंस्करण\n user.Age++\n // JSON के रूप में वापस भेजें\n result, _ := json.Marshal(user)\n return js.ValueOf(string(result))\n}\n\n\n2. दो-तरफा संचार: Go से JavaScript को कॉल करना और इसके विपरीत
\n\nउन्नत एकीकरण के लिए आवश्यक है कि Go मॉड्यूल न केवल कॉल का जवाब दे सके, बल्कि JavaScript वातावरण में कार्रवाई भी शुरू कर सके।
\n\n2.1. JavaScript के लिए Go कॉलबैक का पंजीकरण
\n\nJS से दिखाई देने वाले फ़ंक्शन बनाने के लिए js.FuncOf का उपयोग करें। उनके जीवनचक्र को ठीक से प्रबंधित करना महत्वपूर्ण है:
var callback js.Func\n\nfunc registerCallback() {\n callback = js.FuncOf(func(this js.Value, args []js.Value) interface{} {\n // JS से कॉलबैक प्राप्त करें\n jsCallback := args[0]\n // Go से डेटा के साथ इसे कॉल करें\n go func() {\n // एसिंक्रोनस कार्य का अनुकरण करें\n time.Sleep(100 * time.Millisecond)\n jsCallback.Invoke(js.ValueOf("Go से परिणाम"))\n }()\n