Go में डिपेंडेंसी इंजेक्शन: एक व्यावहारिक मार्गदर्शिका

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

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

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

Go में डिपेंडेंसी इंजेक्शन: सिद्धांत से वास्तविक कोड तक

\n\n

डिपेंडेंसी इंजेक्शन (DI) एक प्रमुख डिज़ाइन पैटर्न है जो ढीले-युग्मित, परीक्षण योग्य और रखरखाव योग्य कोड बनाने में मदद करता है। Go में, सादगी और स्पष्टता के दर्शन के साथ, निर्भरता इंजेक्शन को मैन्युअल रूप से और लाइब्रेरीज़ की मदद से दोनों तरह से लागू किया जा सकता है। इस लेख में, हम Golang में DI को व्यवहार में सही तरीके से लागू करने के तरीके पर चर्चा करेंगे, मैन्युअल दृष्टिकोण के साथ-साथ लोकप्रिय लाइब्रेरी google/wire पर भी विचार करेंगे।

\n\n

1. Go में डिपेंडेंसी इंजेक्शन की आवश्यकता क्यों है?

\n\n

कल्पना करें कि आप उपयोगकर्ताओं के साथ काम करने के लिए एक HTTP सेवा लिख रहे हैं। DI के बिना, आपका कोड इस तरह दिख सकता है:

\n\n
package main\n\nimport "database/sql"\n\ntype UserHandler struct {\n    db *sql.DB\n}\n\nfunc NewUserHandler() *UserHandler {\n    db, _ := sql.Open("postgres", "conn_string")\n    return &UserHandler{db: db}\n}\n\nfunc (h *UserHandler) GetUser(id int) (*User, error) {\n    // h.db के साथ काम करना\n}\n
\n\n

समस्याएँ स्पष्ट हैं:

\n
    \n
  • कठोर युग्मन — हैंडलर स्वयं डेटाबेस बनाता है।
  • \n
  • परीक्षण में कठिनाई — db को मॉक से बदलना असंभव है।
  • \n
  • एकल उत्तरदायित्व का उल्लंघन — हैंडलर निर्भरता बनाने और व्यावसायिक तर्क दोनों के लिए जिम्मेदार है।
  • \n
\n\n

DI बाहर से निर्भरताएँ पास करके इन समस्याओं का समाधान करता है:

\n\n
type UserHandler struct {\n    db Database\n}\n\nfunc NewUserHandler(db Database) *UserHandler {\n    return &UserHandler{db: db}\n}\n\n// अब इसे आसानी से मॉक से बदला जा सकता है\ntype Database interface {\n    GetUser(id int) (*User, error)\n}\n
\n\n

2. मैन्युअल निर्भरता इंजेक्शन: सादगी और नियंत्रण

\n\n

Go को DI के लिए फ्रेमवर्क की आवश्यकता नहीं है। सबसे सरल और पारदर्शी तरीका कंस्ट्रक्टर के माध्यम से निर्भरताएँ पास करना है। आइए एप्लिकेशन के तीन स्तरों वाले एक उदाहरण पर विचार करें: handler → service → repository.

\n\n
// repository/user.go\ntype UserRepository interface {\n    FindByID(id int) (*User, error)\n}\n\ntype postgresUserRepo struct {\n    db *sql.DB\n}\n\nfunc NewPostgresUserRepo(db *sql.DB) *postgresUserRepo {\n    return &postgresUserRepo{db: db}\n}\n\nfunc (r *postgresUserRepo) FindByID(id int) (*User, error) {\n    // कार्यान्वयन\n}\n
\n\n
// service/user.go\ntype UserService struct {\n    repo UserRepository\n}\n\nfunc NewUserService(repo UserRepository) *UserService {\n    return &UserService{repo: repo}\n}\n\nfunc (s *UserService) GetUser(id int) (*User, error) {\n    return s.repo.FindByID(id)\n}\n
\n\n
// handler/user.go\ntype UserHandler struct {\n    svc *UserService\n}\n\nfunc NewUserHandler(svc *UserService) *UserHandler {\n    return &UserHandler{svc: svc}\n}\n\nfunc (h *UserHandler) HandleGetUser(w http.ResponseWriter, r *http.Request) {\n    // h.svc के साथ काम करना\n}\n
\n\n

अब एप्लिकेशन का निर्माण main.go में होता है:

\n\n
func main() {\n    db, _ := sql.Open("postgres", os.Getenv("DB_URL"))\n    \n    repo := NewPostgresUserRepo(db)\n    svc := NewUserService(repo)\n    handler := NewUserHandler(svc)\n    \n    http.HandleFunc("/user", handler.HandleGetUser)\n    log.Fatal(http.ListenAndServe(":8080", nil))\n}\n
\n\n

मैन्युअल DI के लाभ:

\n
    \n
  • पूर्ण पारदर्शिता — आप सभी निर्भरताओं को स्पष्ट रूप से देखते हैं।
  • \n
  • प्रोजेक्ट में कोई जादू या अनावश्यक निर्भरता नहीं।
  • \n
  • छोटे और मध्यम आकार के प्रोजेक्ट के लिए आदर्श।
  • \n
\n\n

नुकसान: जैसे-जैसे एप्लिकेशन बढ़ता है (50+ घटक), मैन्युअल निर्माण बोझिल और त्रुटि-प्रवण हो जाता है।

\n\n

3. google/wire के साथ स्वचालन

\n\n

लाइब्रेरी github.com/google/wire निर्भरता निर्माण के लिए कोड उत्पन्न करती है। यह runtime-कंटेनर नहीं है — यह एक कोड जनरेटर है, जो Go के दर्शन के अनुरूप है।

\n\n

स्थापना:

\n
go get github.com/google/wir                

ब्लॉग

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