Go में आर्किटेक्चरल पैटर्न: गोरूटीन में कैसे न डूबें

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

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

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

परिचय: आर्किटेक्चर विलासिता क्यों नहीं, बल्कि आवश्यकता क्यों है

\n\n

जब आप Go में लिखना शुरू करते हैं, तो सब कुछ सरल लगता है: गोरूटीन उड़ती हैं, चैनल गूंजते हैं, और कंपाइलर गति से खुश करता है। लेकिन एक-दो महीने बीतते हैं, और आपका pet-प्रोजेक्ट package main के साथ 3000 लाइनों के राक्षस में बदल जाता है और प्रार्थना करता है "बस गिरे नहीं"। परिचित लगता है?

\n\n

Go शक्तिशाली उपकरण देता है, लेकिन सख्त सीमाएँ नहीं थोपता। यह फायदा और नुकसान दोनों है। स्पष्ट आर्किटेक्चर के बिना, आप जल्दी से अपनी गोरूटीन में उलझ जाएंगे। यहीं पर Go में आर्किटेक्चरल पैटर्न मदद करते हैं — डिज़ाइन की सामान्य समस्याओं के सिद्ध समाधान।

\n\n

इस लेख में, हम चार प्रमुख पैटर्न पर चर्चा करेंगे जो वास्तव में जीवन को आसान बनाते हैं: Repository, Service Layer, Worker Pool और Pipeline। आप कोड उदाहरण देखेंगे, समझेंगे कि कब कौन सा पैटर्न लागू करना है, और उन्हें तुरंत अपने प्रोजेक्ट में शामिल कर सकेंगे। चलिए शुरू करते हैं!

\n\n

1. Repository Pattern: बिज़नेस लॉजिक को डेटाबेस से अलग करना

\n\n

पहला पैटर्न जो हर Go डेवलपर को सीखना चाहिए — Repository। इसका सार सरल है: बिज़नेस लॉजिक और डेटा स्टोरेज (DB, फ़ाइलें, बाहरी API) के बीच एक परत बनाना।

\n\n

इसकी आवश्यकता क्यों है?

\n
    \n
  • परीक्षण क्षमता: वास्तविक DB को आसानी से मॉक से बदला जा सकता है।
  • \n
  • लचीलापन: PostgreSQL से MongoDB पर जाना? केवल रिपॉजिटरी बदलें।
  • \n
  • कोड की सफाई: handler को नहीं पता कि डेटा कहाँ से आ रहा है — यह रिपॉजिटरी का काम है।
  • \n
\n\n

कार्यान्वयन का उदाहरण

\n

मान लीजिए, हमारे पास एक उपयोगकर्ता मॉडल है:

\n\n
type User struct {\n    ID    int64\n    Name  string\n    Email string\n}
\n\n

हम रिपॉजिटरी इंटरफ़ेस परिभाषित करते हैं:

\n\n
type UserRepository interface {\n    GetByID(ctx context.Context, id int64) (*User, error)\n    Create(ctx context.Context, user *User) error\n    Update(ctx context.Context, user *User) error\n    Delete(ctx context.Context, id int64) error\n}
\n\n

और PostgreSQL के लिए इसका कार्यान्वयन:

\n\n
type PostgresUserRepo struct {\n    db *sql.DB\n}\n\nfunc (r *PostgresUserRepo) GetByID(ctx context.Context, id int64) (*User, error) {\n    user := &User{}\n    err := r.db.QueryRowContext(ctx, "SELECT id, name, email FROM users WHERE id = $1", id).\n        Scan(&user.ID, &user.Name, &user.Email)\n    if err != nil {\n        return nil, fmt.Errorf("get user by id: %w", err)\n    }\n    return user, nil\n}
\n\n

अब आपका handler या सेवा केवल UserRepository इंटरफ़ेस के साथ काम करता है, न कि किसी विशिष्ट DB के साथ। यही है Go में Repository आर्किटेक्चरल पैटर्न क्रियान्वयन में।

\n\n

2. Service Layer: बिज़नेस लॉजिक नियंत्रण में

\n\n

यदि Repository डेटा के लिए जिम्मेदार है, तो Service Layer बिज़नेस नियमों के लिए। यह पैटर्न बिखरे हुए ऑपरेशनों को सार्थक क्रियाओं में एकत्रित करता है।

\n\n

Service Layer के बिना समस्या

\n

अक्सर मैं ऐसा कोड देखता हूँ जहाँ handler सब कुछ करता है: अनुरोध को मान्य करना, अधिकार जाँचना, DB में लिखना और लॉग करना। यह एकल जिम्मेदारी सिद्धांत (SRP) का उल्लंघन करता है।

\n\n

इसे कैसे ठीक करें?

\n

हम सेवा परत शुरू करते हैं:

\n\n
type UserService interface {\n    Register(ctx context.Context, name, email string) (*User, error)\n    GetProfile(ctx context.Context, userID int64) (*User, error)\n}\n\ntype userService struct {\n    repo UserRepository\n    mail MailSender\n}\n\nfunc (s *userService) Register(ctx context.Context, name, email string) (*User, error) {\n    // 1. वैलिडेशन\n    if name == "" || email == "" {\n        return nil, ErrInvalidInput\n    }\n\n    // 2. बिज़नेस लॉजिक: जाँचें कि ईमेल पहले से नहीं है\n    existing, _ := s.repo.GetByEmail(ctx, email)\n    if existing != nil {\n        return nil, ErrEmailAlreadyExists\n    }\n\n    // 3. उपयोगकर्ता बनाएँ\n    user := &User{Name: name, Email: e                

ब्लॉग

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