💻 अत्यधिक विस्तार में FizzBuzz: एक Go दृष्टिकोण 🔗

टॉम डैलिंग (Tom Dalling) के क्लासिक लेख से प्रेरित होकर, यह पोस्ट पड़ताल करती है कि Go का उपयोग करके साधारण FizzBuzz समस्या को किस हद तक ओवर-इंजीनियर किया जा सकता है।

हम सबसे बुनियादी कार्यान्वयन के साथ शुरुआत करेंगे और Go की भाषा विशेषताओं—बुनियादी कंडीशनल्स से लेकर हायर-ऑर्डर फ़ंक्शंस और कॉनकरेंसी (concurrency) तक—का पता लगाने के लिए इसे क्रमिक रूप से रिफैक्टर करेंगे।

📑 विषय-सूची 🔗


🎯 लक्ष्य 🔗

आउटपुट 1 से 15 तक का क्लासिक FizzBuzz अनुक्रम होना चाहिए:

1
2
Fizz
4
Buzz
Fizz
7
8
Fizz
Buzz
11
Fizz
13
14
FizzBuzz

1️⃣ सीधा दृष्टिकोण (आसान) 🔗

हम सबसे सीधे दृष्टिकोण के साथ शुरुआत करते हैं। यह काम पूरा कर देता है, लेकिन इसमें 3 और 5 दोनों के लिए मॉड्यूलो (modulo) लॉजिक को दोहराने की आवश्यकता होती है।

package main

import "fmt"

func main() {
	for i := 1; i <= 15; i++ {
		if i%3 == 0 && i%5 == 0 {
			fmt.Println("FizzBuzz")
		} else if i%3 == 0 {
			fmt.Println("Fizz")
		} else if i%5 == 0 {
			fmt.Println("Buzz")
		} else {
			fmt.Println(i)
		}
	}
}

2️⃣ DRY बनाना (कम दोहराव) 🔗

संख्या 3 और 5, तथा स्ट्रिंग्स "Fizz" और "Buzz" को दोहराने से बचने के लिए, हम परिणामी स्ट्रिंग को क्रमिक रूप से बना सकते हैं। यदि हमारी जाँच के बाद स्ट्रिंग खाली रहती है, तो हम बस संख्या को प्रिंट कर देते हैं।

package main

import "fmt"

func main() {
	for i := 1; i <= 15; i++ {
		res := ""
		
		if i%3 == 0 {
			res += "Fizz"
		}
		if i%5 == 0 {
			res += "Buzz"
		}
		
		if res == "" {
			res = fmt.Sprint(i)
		}
		fmt.Println(res)
	}
}

3️⃣ स्ट्रक्ट्स के साथ पैरामीटराइज्ड (डेटा-संचालित) 🔗

इसके बाद, आइए नियमों को पूरी तरह से अलग निकाल लें।

नोट: मूल लेख में इसके लिए map[int]string का उपयोग किया गया था। हालाँकि, Go जानबूझकर मैप पुनरावृत्ति (iteration) के क्रम को रैंडम रखता है। मैप का उपयोग करने का अर्थ है कि आप कभी-कभी “FizzBuzz” के बजाय “BuzzFizz” प्रिंट कर सकते हैं! इसे ठीक करने के लिए, हम निष्पादन के क्रम की गारंटी देने के लिए स्ट्रक्ट्स के एक स्लाइस (slice) का उपयोग करते हैं।

package main

import "fmt"

type Rule struct {
	Divisor int
	Word    string
}

func run(max int, rules []Rule) []string {
	var all []string
	for i := 1; i <= max; i++ {
		res := ""
		for _, rule := range rules {
			if i%rule.Divisor == 0 {
				res += rule.Word
			}
		}
		if res == "" {
			res = fmt.Sprint(i)
		}
		all = append(all, res)
	}
	return all
}

func main() {
	rules := []Rule{
		{3, "Fizz"},
		{5, "Buzz"},
	}
	
	all := run(15, rules)
	for _, word := range all {
		fmt.Println(word)
	}
}

4️⃣ फ़ंक्शंस के साथ पैरामीटराइज्ड (क्लोज़र / Closures) 🔗

डेटा पास करने के बजाय, क्या हो यदि हम व्यवहार (behavior) पास करें? हम Trigger टाइप को एक ऐसे फ़ंक्शन के रूप में परिभाषित कर सकते हैं जो वर्तमान पुनरावृत्ति (iteration) के आधार पर स्ट्रिंग पॉइंटर को संशोधित करता है।

package main

import "fmt"

type Trigger func(res *string, i int)

func run(max int, triggers []Trigger) []string {
	var all []string
	for i := 1; i <= max; i++ {
		res := ""
		for _, trigger := range triggers {
			trigger(&res, i)
		}
		all = append(all, res)
	}
	return all
}

func main() {
	all := run(15, []Trigger{
		func(res *string, i int) {
			if i%3 == 0 {
				*res += "Fizz"
			}
		},
		func(res *string, i int) {
			if i%5 == 0 {
				*res += "Buzz"
			}
		},
		func(res *string, i int) {
			if *res == "" {
				*res = fmt.Sprint(i)
			}
		},
	})
	
	for _, word := range all {
		fmt.Println(word)
	}
}

5️⃣ हायर-ऑर्डर फ़ंक्शंस (ट्रिगर्स के लिए एक फ़ैक्टरी) 🔗

उन अनाम (anonymous) फ़ंक्शंस को बार-बार लिखना दोहराव भरा है। हम एक फ़ैक्टरी फ़ंक्शन लिखकर इसे DRY बना सकते हैं जो एक फ़ंक्शन लौटाता है। यह Go में क्लोज़र (closures) का लाभ उठाता है।

package main

import "fmt"

type Trigger func(res *string, i int)

func run(max int, triggers []Trigger) []string {
	var all []string
	for i := 1; i <= max; i++ {
		res := ""
		for _, trigger := range triggers {
			trigger(&res, i)
		}
		all = append(all, res)
	}
	return all
}

// create acts as a factory, returning a custom Trigger function
func create(number int, word string) Trigger {
	return func(res *string, i int) {
		if i%number == 0 {
			*res += word
		}
	}
}

func main() {
	all := run(15, []Trigger{
		create(3, "Fizz"),
		create(5, "Buzz"),
		func(res *string, i int) {
			if *res == "" {
				*res = fmt.Sprint(i)
			}
		},
	})
	
	for _, word := range all {
		fmt.Println(word)
	}
}

6️⃣ कॉनकरेंट बनाना (चैनल्स / Channels) 🔗

अंत में, आइए कॉनकरेंसी का उपयोग करके इसे स्वाभाविक (idiomatic) Go बनाएं। परिणामों को एक स्लाइस में जमा करने और उन्हें अंत में लौटाने के बजाय, हम एक गोरूटीन (goroutine) में संख्याओं को प्रोसेस कर सकते हैं और एक चैनल के माध्यम से परिणामों को मुख्य थ्रेड में वापस स्ट्रीम कर सकते हैं।

run में chan<- string सिग्नेचर पर ध्यान दें। यह फ़ंक्शन को केवल चैनल पर डेटा भेजने के लिए सही ढंग से प्रतिबंधित करता है, जो Go में एक अच्छी प्रथा है।

package main

import "fmt"

type Trigger func(res *string, i int)

func run(max int, out chan<- string, triggers []Trigger) {
	for i := 1; i <= max; i++ {
		res := ""
		for _, trigger := range triggers {
			trigger(&res, i)
		}
		out <- res // Stream the result
	}
	close(out) // Always close the channel when finished
}

func create(number int, word string) Trigger {
	return func(res *string, i int) {
		if i%number == 0 {
			*res += word
		}
	}
}

func main() {
	// Create an unbuffered channel
	results := make(chan string)
	
	// Start the generation in a background goroutine
	go run(15, results, []Trigger{
		create(3, "Fizz"),
		create(5, "Buzz"),
		func(res *string, i int) {
			if *res == "" {
				*res = fmt.Sprint(i)
			}
		},
	})
	
	// Range over the channel to read values as they arrive
	for word := range results {
		fmt.Println(word)
	}
}

🏁 निष्कर्ष 🔗

FizzBuzz जैसी सरल समस्या को ओवर-इंजीनियर करके, हमने स्ट्रक्चरल लूप्स, डेटा-संचालित नियमों (और क्यों मैप पुनरावृत्ति क्रम मायने रखता है!), क्लोज़र, हायर-ऑर्डर फ़ंक्शंस और अंत में, गोरूटीन्स और चैनल्स को समझा है। यह इस बात की एक बेहतरीन याद दिलाता है कि Go में एक ही समस्या को हल करने के कितने सारे तरीके हैं!


📚 मेरी निःशुल्क ई-बुक डाउनलोड करें 🔗

काउए की जीवनशैली का क्यूरेटेड ऑफ़लाइन संस्करण प्राप्त करें—🍏 स्वास्थ्य, 💰 धन, ❤️ प्रेम और 🧘 अर्थ को बेहतर बनाने के लिए एक व्यावहारिक मार्गदर्शिका।

काउए की जीवनशैली

काउए की जीवनशैली

📬 न्यूज़लेटर की सदस्यता लें 🔗

जब भी मैं बेहतर जीवन जीने पर नए निबंध, पुस्तक सारांश और व्यावहारिक गाइड प्रकाशित करूँ, तो सूचना प्राप्त करें। कोई स्पैम नहीं—कभी भी सदस्यता समाप्त करें।


💬 टिप्पणियाँ और चर्चा 🔗

क्या आपका कोई प्रश्न, दृष्टिकोण या सुझाव है? नीचे अपने विचार साझा करें। टिप्पणियाँ GitHub Discussions (विज्ञापन-मुक्त और स्पैम-मुक्त) द्वारा संचालित हैं—टिप्पणी करने या प्रतिक्रिया देने के लिए नीचे Sign in with GitHub पर क्लिक करें (निःशुल्क GitHub खाता बनाने में एक मिनट से भी कम समय लगता है)।



अंतिम अपडेट: 11 अक्टू॰ 2026.

अस्वीकरण (DISCLAIMER): इस साइट की सामग्री केवल सूचनात्मक और शैक्षिक उद्देश्यों के लिए है और यह चिकित्सा, मनोवैज्ञानिक, वित्तीय, निवेश, कर या कानूनी सलाह का गठन नहीं करती है। यहाँ प्रस्तुत विचार, संकलन और राय पूरी तरह से मेरे अपने हैं और मेरे नियोक्ता का प्रतिनिधित्व नहीं करते हैं। पुस्तकों, व्याख्यानों और लेखों के सारांश स्वतंत्र शैक्षिक टिप्पणियाँ हैं और उनके संबंधित लेखकों की बौद्धिक संपदा बने रहते हैं। संपादन, स्वरूपण और संश्लेषण में सहायता के लिए AI उपकरणों का उपयोग किया जा सकता है; यद्यपि सटीकता सुनिश्चित करने का हर संभव प्रयास किया जाता है, फिर भी त्रुटियाँ हो सकती हैं। गोपनीयता (PRIVACY): यह साइट वैकल्पिक न्यूज़लेटर सदस्यता (follow.it), टिप्पणियों (giscus / GitHub Discussions) और एम्बेडेड मीडिया (YouTube) के लिए तृतीय-पक्ष सेवाओं का उपयोग करती है, जो अपनी संबंधित गोपनीयता नीतियों के अनुसार आगंतुकों के IP पते और कुकीज़ को संसाधित कर सकती हैं।