Was ist Wire und warum braucht man es?
Wire ist eine Bibliothek zur Abhängigkeitsinjektion (Dependency Injection, DI) für die Programmiersprache Go, entwickelt vom Google-Team. Im Gegensatz zu vielen anderen DI-Frameworks, die zur Laufzeit (Runtime) arbeiten, nutzt Wire die Codegenerierung während der Kompilierung. Das ist der entscheidende Unterschied: Wire analysiert Ihren Code und generiert eine wire_gen.go-Datei, die die gesamte Logik zur Verkettung der Abhängigkeiten enthält. Dieser Ansatz vermeidet Fehler, die durch Reflektion (reflect) entstehen, und macht den Code vollständig typisiert.
Wozu braucht man das?
- Vereinfachte Konfiguration: Statt alle Abhängigkeiten manuell in
main.gozu erstellen, übernimmt Wire dies automatisch. - Testen: Sie können echte Implementierungen problemlos durch Mocks für Unit-Tests ersetzen.
- Sauberer Code: Der Code wird modularer und weniger stark gekoppelt (low coupling).
- Typsicherheit: Konfigurationsfehler werden bereits zur Kompilierzeit erkannt, nicht erst zur Laufzeit.
Wire ist ideal für große Projekte, in denen die Anzahl der Abhängigkeiten in die Dutzende oder Hunderte geht.
Installation
Wire ist keine Bibliothek im herkömmlichen Sinne (wie ein Paket, das Sie importieren). Es ist ein Kommandozeilen-Tool (CLI). Die Installation erfolgt über den standardmäßigen Go-Paketmanager:
go install github.com/google/wire/cmd/wire@latest
Nach der Ausführung dieses Befehls ist die Binärdatei wire in Ihrem $GOPATH/bin (oder $GOBIN) verfügbar. Stellen Sie sicher, dass dieses Verzeichnis zur Umgebungsvariablen PATH hinzugefügt wurde.
Überprüfen Sie die Installation:
wire help
Wenn Sie die Hilfe zu den Befehlen sehen – alles ist bereit für den Start.
Schnellstart mit Codebeispiel
Lassen Sie uns eine einfache Anwendung erstellen, die einen Benutzer begrüßt. Wir haben drei Komponenten: Message, Greeter (Begrüßer) und Event (Ereignis).
Schritt 1: Projektstruktur
myapp/
├── main.go
├── wire.go
└── wire_gen.go (wird generiert)
Schritt 2: Komponenten erstellen (main.go)
package main
import "fmt"
// Message — eine einfache Struktur, die einen Text enthält.
type Message struct {
Text string
}
// NewMessage — Konstruktor für Message.
func NewMessage(text string) Message {
return Message{Text: text}
}
// Greeter — Struktur, die mit Message begrüßt.
type Greeter struct {
Message Message
}
// NewGreeter — Konstruktor für Greeter.
func NewGreeter(m Message) Greeter {
return Greeter{Message: m}
}
// Greet — Methode, die die Begrüßung zurückgibt.
func (g Greeter) Greet() Message {
return g.Message
}
// Event — Struktur, die ein Ereignis darstellt.
type Event struct {
Greeter Greeter
}
// NewEvent — Konstruktor für Event.
func NewEvent(g Greeter) Event {
return Event{Greeter: g}
}
// Start — Methode, die das Ereignis startet.
func (e Event) Start() {
msg := e.Greeter.Greet()
fmt.Println(msg.Text)
}
func main() {
// Manuelle Erstellung der Abhängigkeiten (ohne Wire)
message := NewMessage("Hallo, Wire!")
greeter := NewGreeter(message)
event := NewEvent(greeter)
event.Start()
}
Schritt 3: Datei wire.go erstellen
Diese Datei ist der "Provider" für Wire. Sie enthält Initialisierungsfunktionen (Provider) und eine Funktion, die Wire mitteilt, was zusammengebaut werden soll.
//go:build wireinject
// +build wireinject
package main
import "github.com/google/wire"
// InitializeEvent — Funktion, die Wire zur Codegenerierung verwendet.
// Sie deklariert, dass wir ein Event benötigen, und Wire erstellt selbst den Abhängigkeitsgraphen.
func InitializeEvent(text string) Event {
wire.Build(NewEvent, NewGreeter, NewMessage)
return Event{} // Diese Zeile wird nicht ausgeführt, sie dient nur der