गो प्रोजेक्ट को कई फ़ाइलों के साथ कैसे व्यवस्थित करें: अंदर की बात

शुरुआती लोगों के लिए ऑनलाइन Python प्रशिक्षक

Python आसानी से सीखें बिना सिद्धांत के बोझ के। स्वचालित जांच के साथ व्यावहारिक कार्य हल करें और ब्राउज़र में सीधे कोड लिखें।

पाठ्यक्रम शुरू करें

एक फ़ाइल वाला Go-प्रोजेक्ट आसान है। और दस फ़ाइलों वाला?

\n\n

कल्पना करें: आप Go में लॉग पार्स करने के लिए एक उपयोगिता लिख रहे हैं। पहले सब कुछ एक फ़ाइल main.go में समा जाता है। काम करता है, सब ठीक है। लेकिन एक हफ्ते बाद कोड बढ़ जाता है: फ़ाइलें पढ़ने, फ़िल्टर करने, डेटाबेस में डेटा भेजने के लिए फ़ंक्शन आ जाते हैं। एक फ़ाइल 2000 लाइनों का राक्षस बन जाती है। परिचित लग रहा है?

\n\n

यहाँ वह सवाल उठता है जो हर दूसरे शुरुआती को परेशान करता है (और जिसने Stack Overflow पर हज़ारों व्यूज़ जुटाए हैं): कई फ़ाइलों वाले Go-प्रोजेक्ट को सही तरीके से कैसे व्यवस्थित करें? सिर्फ कोड को फ़ोल्डरों में बिखेरना नहीं, बल्कि इसे इस तरह करना कि यह काम करे, कंपाइल हो और undefined या import cycle not allowed जैसी त्रुटियाँ न दें।

\n\n

इस लेख में हम सिर्फ एक टेम्पलेट नहीं देंगे। हम Go कंपाइलर के अंदर झाँकेंगे और समझेंगे कि फ़ाइलों, पैकेजों और मॉड्यूल का संबंध वास्तव में कैसे काम करता है। आप जानेंगे कि go run *.go कब काम करता है और कब नहीं, और ऐसी आर्किटेक्चर कैसे बनाएँ जो स्केलेबल हो।

\n\n

फ़ाइल, पैकेज, मॉड्यूल — मूलभूत पदानुक्रम

\n\n

कोड में कूदने से पहले, आइए तीन मुख्य अवधारणाओं को समझें। इनके बिना Go-प्रोजेक्ट का संगठन अंदाज़ा लगाने जैसा हो जाता है।

\n\n
    \n
  • फ़ाइल (.go) — यह सिर्फ कोड वाली एक टेक्स्ट फ़ाइल है। अपने आप में इसका कंपाइलर के लिए कोई मतलब नहीं है।
  • \n
  • पैकेज (package) — यह एक ही डायरेक्टरी में मौजूद फ़ाइलों का एक तार्किक समूह है। एक फ़ोल्डर की सभी फ़ाइलों में अनिवार्य रूप से एक ही package घोषणा होनी चाहिए। अगर फ़ोल्डर में अलग-अलग पैकेज वाली फ़ाइलें हैं, तो कंपाइलर त्रुटि देगा।
  • \n
  • मॉड्यूल (go.mod) — यह आपके प्रोजेक्ट की जड़ है। यह मॉड्यूल का नाम, उसकी निर्भरताएँ और Go संस्करण निर्धारित करता है। एक मॉड्यूल में कई पैकेज हो सकते हैं।
  • \n
\n\n

सुनहरा नियम: एक निर्देशिका = एक पैकेज। अपवाद टेस्ट हैं, लेकिन उन पर बाद में।

\n\n

व्यावहारिक उदाहरण: प्रोजेक्ट "लॉग विश्लेषक"

\n\n

आइए एक छोटा प्रोजेक्ट बनाएँ जो लॉग फ़ाइल पढ़ता है, कीवर्ड के आधार पर पंक्तियों को फ़िल्टर करता है और परिणाम दिखाता है। हम पहले इसे "सीधे" (एक फ़ाइल) करेंगे, फिर इसे सही तरीके से कई फ़ाइलों में विभाजित करेंगे।

\n\n

चरण 1: सब कुछ एक फ़ाइल में (खराब)

\n\n
// main.go\npackage main\n\nimport (\n    "bufio"\n    "fmt"\n    "os"\n    "strings"\n)\n\nfunc readLog(path string) ([]string, error) {\n    file, err := os.Open(path)\n    if err != nil {\n        return nil, err\n    }\n    defer file.Close()\n\n    var lines []string\n    scanner := bufio.NewScanner(file)\n    for scanner.Scan() {\n        lines = append(lines, scanner.Text())\n    }\n    return lines, scanner.Err()\n}\n\nfunc filterLines(lines []string, keyword string) []string {\n    var result []string\n    for _, line := range lines {\n        if strings.Contains(line, keyword) {\n            result = append(result, line)\n        }\n    }\n    return result\n}\n\nfunc main() {\n    lines, err := readLog("server.log")\n    if err != nil {\n        fmt.Println("त्रुटि:", err)\n        return\n    }\n    filtered := filterLines(lines, "ERROR")\n    for _, l := range filtered {\n        fmt.Println(l)\n    }\n}\n
\n\n

यह काम करता है। लेकिन कल्पना करें कि readLog जटिल हो जाता है (gzip, एन्कोडिंग का समर्थन चाहिए), और filterLines रेगुलर एक्सप्रेशन से भर जाता है। फ़ाइल अपठनीय हो जाएगी।

\n\n

चरण 2: पैकेजों में विभाजित करना (सही)

\n\n

निर्देशिका संरचना बनाएँ:

\n\n
log-analyzer/\n├── go.mod\n├── main.go\n└── pkg/\n    └── logreader/\n        ├── reader.go\n        └── filter.go\n
\n\n

मॉड्यूल आरंभ करें:

\n\n
go mod init log-analyzer
\n\n

अब logreader पैकेज का कोड लिखें। ध्यान दें: pkg/logreader/ फ़ोल्डर की सभी फ़ाइलों में package logreader है।

\n\n

pkg/logreader/reader.go

\n\n
package logreader

ब्लॉग

पुस्तक अनुशंसाएँ