Go में एसिंक्रोनस प्रोग्रामिंग: सिद्धांत से अभ्यास तक
\n\nGo (Golang) अपने अंतर्निहित एसिंक्रोनस प्रोग्रामिंग समर्थन के लिए प्रसिद्ध है। कई अन्य भाषाओं के विपरीत, जहां एसिंक्रोनसिटी के लिए जटिल लाइब्रेरी और कॉलबैक की आवश्यकता होती है, Go सुरुचिपूर्ण और शक्तिशाली प्रिमिटिव प्रदान करता है: गोरूटीन (goroutines) और चैनल (channels)। इस गाइड में, हम सभी प्रमुख अवधारणाओं को व्यावहारिक रूप से समझेंगे, ताकि आप Go में कुशल, समानांतर कोड लिख सकें।
\n\nगोरूटीन (Goroutines) क्या हैं?
\n\nगोरूटीन एक हल्का निष्पादन थ्रेड है, जिसे Go रनटाइम द्वारा प्रबंधित किया जाता है। सिस्टम थ्रेड के विपरीत, गोरूटीन बहुत कम संसाधनों का उपभोग करते हैं (केवल कुछ किलोबाइट स्टैक), जिससे एक साथ हजारों और यहां तक कि लाखों गोरूटीन चलाना संभव होता है।
\n\nगोरूटीन शुरू करना बहुत आसान है - बस फंक्शन कॉल से पहले कीवर्ड go जोड़ें:
package main\n\nimport (\n "fmt"\n "time"\n)\n\nfunc sayHello() {\n fmt.Println("गोरूटीन से नमस्ते!")\n}\n\nfunc main() {\n go sayHello() // गोरूटीन शुरू करें\n \n time.Sleep(time.Millisecond * 100) // गोरूटीन को निष्पादित होने का समय दें\n fmt.Println("मुख्य फंक्शन समाप्त")\n}\n\nध्यान दें: यदि time.Sleep नहीं जोड़ा जाता है, तो प्रोग्राम गोरूटीन शुरू होने से पहले समाप्त हो सकता है। सिंक्रोनाइज़ेशन के लिए, अन्य तंत्रों का उपयोग करना बेहतर है, जिन्हें हम नीचे देखेंगे।
चैनल (Channels): गोरूटीन के बीच डेटा स्थानांतरण
\n\nचैनल टाइप किए गए "पाइप" हैं, जिनके माध्यम से गोरूटीन डेटा का आदान-प्रदान कर सकते हैं। चैनल make फंक्शन और chan ऑपरेटर का उपयोग करके बनाया जाता है। डेटा को चैनल में <- ऑपरेटर का उपयोग करके भेजा जाता है, और इसे <- का उपयोग करके प्राप्त किया जाता है, लेकिन चैनल के बाईं ओर।
बफ़र किए गए और बिना बफ़र वाले चैनल का उदाहरण देखें:
\n\npackage main\n\nimport "fmt"\n\nfunc main() {\n // बिना बफ़र वाला चैनल (आकार 0)\n ch := make(chan string)\n \n go func() {\n ch <- "गोरूटीन से संदेश" // डेटा भेजें\n }()\n \n msg := <-ch // डेटा प्राप्त करें (तब तक ब्लॉक रहेगा जब तक संदेश न आए)\n fmt.Println(msg)\n \n // बफ़र किया गया चैनल (आकार 2)\n bufferedCh := make(chan int, 2)\n bufferedCh <- 10\n bufferedCh <- 20\n \n fmt.Println(<-bufferedCh) // 10\n fmt.Println(<-bufferedCh) // 20\n}\n\nमहत्वपूर्ण: बिना बफ़र वाला चैनल प्रेषक को तब तक ब्लॉक करता है जब तक प्राप्तकर्ता डेटा प्राप्त नहीं कर लेता। बफ़र किया गया चैनल प्रेषक को तभी ब्लॉक करता है जब बफ़र भर जाता है।
\n\nSelect: चैनलों का मल्टीप्लेक्सिंग
\n\nselect ऑपरेटर एक गोरूटीन को एक साथ कई चैनलों की प्रतीक्षा करने और जो पहले तैयार हो, उसे संसाधित करने की अनुमति देता है। यह चैनलों के लिए switch के समान है। select टाइमआउट बनाने, संचालन रद्द करने और नॉन-ब्लॉकिंग जांच के लिए एक शक्तिशाली उपकरण है।
package main\n\nimport (\n "fmt"\n "time"\n)\n\nfunc main() {\n ch1 := make(chan string)\n ch2 := make(chan string)\n \n // गोरूटीन 1: 1 सेकंड के बाद डेटा भेजता है\n go func() {\n time.Sleep(1 * time.Second)\n ch1 <- "चैनल 1 से डेटा"\n }()\n \n // गोरूटीन 2: 2 सेकंड के बाद डेटा भेजता है\n go func() {\n time.Sleep(2 * time.Second)\n ch2 <- "चैनल 2 से डेटा"\n }()\n \n select {\n case msg1 := <-ch1:\n fmt.Println("प्राप्त:", msg1)\n case msg2 := <-ch2:\n fmt.Println("प्राप्त:", msg2)\n case <-time.After(500 * time.Millisecond):\n fmt.Println("टाइमआउट! 500 मि.से. में कोई भी चैनल उत्तर नहीं दिया")\n }\n}\n\nइस उदाहरण में, select टाइमआउट पर काम करेगा, क्योंकि 500 मि.से. में कोई भी चैनल तैयार नहीं है। यदि हम टाइमआउट हटा दें, तो प्रोग्राम पहले तैयार चैनल की प्रतीक्षा करेगा।