Dependency Injection Container für Go (Golang): Wire, Dig und Uber FX

Online Python-Trainer für Anfänger

Lernen Sie Python einfach ohne theoretische Überlastung. Lösen Sie praktische Aufgaben mit automatischer Überprüfung und schreiben Sie Code direkt im Browser.

Kurs starten

Dependency Injection Container für Go (Golang): Wire, Dig und Uber FX

\n\n

Dependency Injection (DI) ist ein Entwurfsmuster, bei dem ein Objekt seine Abhängigkeiten von außen erhält, anstatt sie selbst zu erstellen. In Go (Golang) ist DI besonders nützlich, um modularen, testbaren und skalierbaren Code zu erstellen. Die beliebtesten DI-Werkzeuge für Go sind Google Wire, Uber Dig und Uber FX. In diesem Artikel betrachten wir jedes davon, ihre Besonderheiten und Anwendungsbeispiele.

\n\n

Warum wird Dependency Injection in Go benötigt?

\n

Go ist eine statisch typisierte Sprache mit expliziter Parameterübergabe. Ohne DI erstellen Entwickler oft globale Variablen oder Fabriken, was das Testen und die Wartung erschwert. DI-Container lösen diese Probleme:

\n
    \n
  • Geringe Kopplung — Komponenten hängen von Schnittstellen ab, nicht von konkreten Implementierungen.
  • \n
  • Testbarkeit — Abhängigkeiten können leicht durch Mocks ersetzt werden.
  • \n
  • Vereinfachte Konfiguration — Der Container löst automatisch den Abhängigkeitsgraphen auf.
  • \n
\n\n

Google Wire — Codegenerierung zur Kompilierzeit

\n

Wire von Google ist kein Laufzeit-Container, sondern ein Code-Generator. Es analysiert Konstruktorfunktionen und generiert zur Kompilierzeit Code zur Verknüpfung von Abhängigkeiten. Dies führt zu null Laufzeit-Overhead und früher Fehlererkennung.

\n\n

Wire installieren

\n
go install github.com/google/wire/cmd/wire@latest
\n\n

Beispiel zur Verwendung von Wire

\n

Angenommen, wir haben einen Dienst, der von einer Datenbank und einem Logger abhängt:

\n
// main.go\npackage main\n\nimport "fmt"\n\ntype Logger struct{}\n\nfunc NewLogger() Logger { return Logger{} }\n\nfunc (l Logger) Log(msg string) { fmt.Println(msg) }\n\ntype Database struct {\n    logger Logger\n}\n\nfunc NewDatabase(logger Logger) Database {\n    return Database{logger: logger}\n}\n\ntype Service struct {\n    db  Database\n    log Logger\n}\n\nfunc NewService(db Database, log Logger) Service {\n    return Service{db: db, log: log}\n}
\n

Jetzt erstellen wir eine Datei wire.go mit einer Anweisung für Wire:

\n
// wire.go\n//go:build wireinject\n// +build wireinject\n\npackage main\n\nimport "github.com/google/wire"\n\nfunc InitializeService() Service {\n    wire.Build(NewLogger, NewDatabase, NewService)\n    return Service{}\n}
\n

Wir starten die Generierung:

\n
wire
\n

Wire erstellt eine Datei wire_gen.go mit fertigem Initialisierungscode:

\n
// wire_gen.go\n// Code generated by Wire. DO NOT EDIT.\n\npackage main\n\nfunc InitializeService() Service {\n    logger := NewLogger()\n    database := NewDatabase(logger)\n    service := NewService(database, logger)\n    return service\n}
\n

Vorteile von Wire:

\n
    \n
  • Fehler zur Kompilierzeit.
  • \n
  • Kein Reflection, hohe Leistung.
  • \n
  • Einfacher und vorhersagbarer Code.
  • \n
\n

Nachteile von Wire:

\n
    \n
  • Erfordert einen separaten Generierungsschritt.
  • \n
  • Schwierig mit dynamischen Abhängigkeiten zu verwenden.
  • \n
\n\n

Uber Dig — Laufzeit-Container mit Reflection

\n

Dig von Uber ist ein Container, der zur Laufzeit arbeitet. Es verwendet Reflection zur Typanalyse und automatischen Auflösung von Abhängigkeiten. Dig bietet eine einfache API zum Registrieren von Konstruktoren und Abrufen von Objekten.

\n\n

Dig installieren

\n
go get go.uber.org/dig
\n\n

Beispiel zur Verwendung von Dig

\n
package main\n\nimport (\n    "fmt"\n    "go.uber.org/dig"\n)\n\ntype Config struct {\n    Port int\n}\n\nfunc NewConfig() *Config {\n    return &Config{Port: 8080}\n}\n\ntype Server struct {\n    config *Config\n}\n\nfunc NewServer(c *Config) *Server {\n    return &Server{config: c}\n}\n\nfunc (s *Server) Start() {\n    fmt.Print                    

Empfehlungen