Go में DSL: अपने कोड को एक नई भाषा में बदलें
\n\nकल्पना करें कि आप एक ऑर्डर प्रोसेसिंग सिस्टम लिख रहे हैं। हर दिन प्रबंधक अनुरोध करते हैं: "मॉस्को के सभी ग्राहकों के लिए 10% की छूट जोड़ें, लेकिन केवल तभी जब ऑर्डर की राशि 5000 से अधिक हो।" आप कोड में जाते हैं, if-else को ठीक करते हैं, परीक्षण करते हैं, डिप्लॉय करते हैं। एक सप्ताह बाद - एक नया अनुरोध: "VIP के लिए 15% की छूट, यदि तीन से अधिक आइटम हों।" परिचित लगता है?
\n\nक्या होगा यदि प्रबंधक स्वयं ऐसे नियम लिख सकें? आपकी भागीदारी के बिना। प्रोडक्शन को तोड़ने के जोखिम के बिना। यही कारण है कि डोमेन-विशिष्ट भाषाएं (DSL) मौजूद हैं - कॉम्पैक्ट भाषाएं जो किसी विशिष्ट कार्य के लिए अनुकूलित होती हैं। और Go, अपनी सादगी और प्रदर्शन के साथ, ऐसे DSL बनाने के लिए आदर्श है।
\n\nइस लेख में, हम Go में DSL बनाने के तरीके पर चर्चा करेंगे - सरल एम्बेडेड समाधानों से लेकर पूर्ण बाहरी पार्सर तक। आप सीखेंगे कि दिनचर्या को कैसे स्वचालित करें और उपयोगकर्ताओं को एक ऐसा उपकरण दें जिसे वे बिना प्रोग्रामिंग के समझ सकें।
\n\nDSL क्या है और Go में इसकी आवश्यकता क्यों है?
\n\nDSL (Domain-Specific Language) एक प्रोग्रामिंग भाषा है जो एक संकीर्ण क्षेत्र के लिए बनाई गई है। सामान्य-उद्देश्यीय भाषाओं (Go, Python, Java) के विपरीत, DSL एक कार्य को हल करती है, लेकिन इसे सुरुचिपूर्ण ढंग से करती है।
\n\nजीवन से उदाहरण:
\n- \n
- SQL - डेटाबेस के साथ काम करने के लिए DSL। \n
- Regex - टेक्स्ट में पैटर्न खोजने के लिए DSL। \n
- HTML - वेब पेजों को मार्कअप करने के लिए DSL। \n
Go में DSL का उपयोग इसके लिए किया जाता है:
\n- \n
- कॉन्फ़िगरेशन - YAML/JSON के बजाय अपनी भाषा में तर्क लिख सकते हैं। \n
- व्यावसायिक नियम - विश्लेषकों को प्रोग्रामर के बिना तर्क बदलने की अनुमति देना। \n
- परीक्षण - पठनीय रूप में परिदृश्यों का वर्णन करना। \n
- डेटा प्रोसेसिंग - ट्रांसफ़ॉर्मेशन पाइपलाइन बनाना। \n
Go को संयोग से नहीं चुना गया है: इसका कंपाइलर तेज़ है, सिंटैक्स संक्षिप्त है, और अंतर्निहित उपकरण (जैसे text/scanner या go/ast) पार्सिंग को सरल बनाते हैं। लेकिन मुख्य बात यह है कि Go आपको आंतरिक DSL (Go के सिंटैक्स में एम्बेडेड) और बाहरी DSL (अपने स्वयं के सिंटैक्स और पार्सर के साथ) दोनों बनाने की अनुमति देता है।
Go में आंतरिक DSL: भाषा के सिंटैक्स का उपयोग करना
\n\nआंतरिक DSL लाइब्रेरीज़ हैं जो एक अलग भाषा की तरह दिखती हैं, लेकिन Go के सिंटैक्स का उपयोग करती हैं। उन्हें पार्सर लिखने की आवश्यकता नहीं होती है: आप बस ऐसे फ़ंक्शन लिखते हैं जो कॉल की श्रृंखला में "जुड़ते" हैं।
\n\nउदाहरण: छूट नियमों के लिए DSL
\n\nमान लीजिए, हम चाहते हैं कि नियम इस तरह दिखें:
\n\ndiscount := Rule("VIP छूट").\n When(City("मॉस्को")).\n When(OrderSum > 5000).\n Apply(Discount(10))\n\nGo में इसे कैसे लागू करें? हम Builder पैटर्न और उच्च-क्रम फ़ंक्शन का उपयोग करते हैं:
\n\npackage main\n\nimport "fmt"\n\n// Rule - नियम की संरचना\ntype Rule struct {\n Name string\n Checks []func(order map[string]interface{}) bool\n Discount int\n}\n\n// When एक शर्त जोड़ता है\nfunc (r *Rule) When(check func(order map[string]interface{}) bool) *Rule {\n r.Checks = append(r.Checks, check)\n return r\n}\n\n// Apply छूट सेट करता है\nfunc (r *Rule) Apply(discount int) *Rule {\n r.Discount = discount\n return r\n}\n\n// Evaluate जांचता है कि ऑर्डर मेल खाता है या नहीं\nfunc (r *Rule) Evaluate(order map[string]interface{}) bool {\n for _, check := range r.Checks {\n if !check(order) {\n return false\n }\n }\n return true\n}\n\n// सहायक शर्त फ़ंक्शन\nfunc City(city string) func(map[string]interface{}) bool {\n return func(order map[string]interface{}) bool {\n return order["city"] == city\n }\n}\n\nfunc OrderSum(order map[string]interface{}) int {\n return order["sum"].(int)\n}\n\n// क्लोज़र के माध्यम से > ऑपरेटर का ओवरलोडिंग\nfunc GreaterThan(a func(map[string]interface{}) int, b