Enterprise Go: Wie man Code schreibt, den man dem CTO zeigen kann

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

Go in der Großindustrie: Warum es längst nicht mehr nur "eine Sprache für Microservices" ist

\n\n

Wenn Sie "Enterprise Go" hören, was kommt Ihnen in den Sinn? Langweilige Unternehmensrichtlinien? Endlose Code-Reviews? Oder vielleicht das Gefühl, dass Go nur für Startups und DevOps ist?

\n\n

Tatsächlich ist Go im Enterprise-Umfeld eine völlig andere Stufe der Disziplin und Ingenieurskultur. In großen Unternehmen (Uber, Dropbox, Salesforce, Twitch) schreibt man mit Go nicht nur Microservices, sondern ganze Plattformen, die Millionen von Anfragen pro Sekunde verarbeiten. Und hier reicht "es funktioniert einfach" nicht aus.

\n\n

In diesem Artikel analysieren wir die wichtigsten Besonderheiten der Go-Entwicklung im Enterprise: vom Paketdesign bis zum Production-Logging. Es wird viel Code und wenig Fülltext geben.

\n\n

1. Architektur: Wiederholen Sie nicht den Fehler "Monolith in Microservices"

\n\n

Das häufigste Problem, das ich in Go-Projekten auf Enterprise-Niveau sehe, ist der Versuch, eine Java-ähnliche Architektur auf Go zu übertragen. Das Ergebnis: Hunderte von unnötigen Interfaces und Abstraktionsebenen, die die Entwicklung nur verlangsamen.

\n\n

Die Regel "Package by feature, not by layer"

\n\n

Anstatt Ordner wie /models, /handlers, /services zu erstellen, gruppieren Sie nach Geschäftsdomänen:

\n\n
myapp/\n├── cmd/\n│   └── server/\n│       └── main.go\n├── internal/\n│   ├── user/          # Alles, was mit Benutzern zu tun hat\n│   │   ├── handler.go\n│   │   ├── service.go\n│   │   ├── repository.go\n│   │   └── user.go    # Datenmodell\n│   ├── payment/       # Alles, was mit Zahlungen zu tun hat\n│   │   ├── handler.go\n│   │   ├── service.go\n│   │   ├── gateway.go\n│   │   └── payment.go\n│   └── pkg/           # Allgemeine Hilfsmittel\n└── go.mod
\n\n

Dieser Ansatz ist eine der Best Practices für Go im Enterprise. Er reduziert die Kopplung (Coupling) und macht den Code vorhersagbar. Wenn ein neuer Entwickler das Projekt öffnet, sieht er sofort die Geschäftslogik, nicht die Abstraktionsebenen.

\n\n

Interfaces: Akzeptieren Sie Interfaces, geben Sie Strukturen zurück

\n\n

Dies ist ein klassischer Ratschlag aus der Go-Community, aber im Enterprise ist er entscheidend. Interfaces sollten klein sein (1-2 Methoden) und dort definiert werden, wo sie verwendet werden, nicht dort, wo sie implementiert werden.

\n\n
// SCHLECHT: Interface neben der Implementierung definiert\npackage user\n\ntype UserRepository interface {\n    FindByID(id string) (*User, error)\n    Save(user *User) error\n}\n\ntype postgresRepo struct { ... }\n\n// GUT: Interface dort, wo es benötigt wird\npackage user\n\ntype Storage interface {\n    Get(id string) (*User, error)\n    Put(user *User) error\n}\n\ntype service struct {\n    db Storage\n}\n\nfunc NewService(db Storage) *service {\n    return &service{db: db}\n}
\n\n

Warum ist das wichtig? Weil Sie im Enterprise oft die Backends wechseln (PostgreSQL -> CockroachDB, Redis -> KeyDB). Interfaces, die auf der Verbraucherseite definiert sind, ermöglichen dies schmerzfrei.

\n\n

2. Fehlerbehandlung: Hören Sie auf, _ zu ignorieren

\n\n

Go hat keine Ausnahmen, und das ist großartig. Aber in Enterprise-Projekten sind Fehler nicht einfach nur if err != nil. Es ist eine ganze Kultur.

\n\n

Wrappen oder nicht wrappen?

\n\n

Verwenden Sie fmt.Errorf mit %w, um Fehlerketten zu erstellen. Dies bewahrt den Aufrufstapel und vereinfacht das Debugging.

\n\n
func (s *service) ProcessOrder(ctx context.Context, orderID string) error {\n    order, err := s.orderRepo.Get(ctx, orderID)\n    if err != nil {\n        return fmt.Errorf("getting order %s: %w", orderID, err)\n    }\n\n    if err := s.paymentGateway.Charge(ctx, order.Amount); err != nil {\n        return fmt.Errorf("charging for order %s: %w", orderID, err)\n    }\n\n    return nil\n}
\n\n

Auf der obersten Ebene (im Handler/Middleware) verwenden Sie errors.Is() und errors.As(), um Fehlertypen zu überprüfen:

\n\n
if errors.Is(err, ErrNotFo                

Blogs

Buchempfehlungen