Warum Go und PostgreSQL das ideale Paar sind?
\n\nIn der Welt der Backend-Entwicklung haben sich Go (oder Golang) und PostgreSQL als leistungsstarkes Duo für die Erstellung hochlastbarer und zuverlässiger Systeme etabliert. Go bietet uns unglaubliche Leistung, Einfachheit und hervorragende Unterstützung für Nebenläufigkeit, während PostgreSQL eine industrielle Datenbank mit umfangreichen Funktionen, Zuverlässigkeit und Erweiterbarkeit ist. Durch ihre Kombination erhalten Sie einen Stack, der den Belastungen eines Startups und den Anforderungen eines Enterprise-Projekts standhält.
\n\nIn diesem Artikel gehen wir nicht nur oberflächlich auf die Syntax ein. Wir erstellen eine umfassende praktische Anleitung: von der Installation des Treibers bis zur Optimierung des Verbindungspools und der Arbeit mit Transaktionen. Sie erfahren, wie Sie typische Fehler vermeiden und effizienten Code in Go für die Arbeit mit PostgreSQL schreiben. Los geht's!
\n\nErste Schritte: Treiber auswählen und verbinden
\n\nDas Erste, was Sie tun müssen, ist den Treiber zu installieren. In der Go-Welt gibt es zwei Hauptkandidaten:
\n- \n
- lib/pq – klassisch, einfach, wird aber nicht mehr aktiv unterstützt. \n
- pgx – modern, schnell, wird aktiv weiterentwickelt, unterstützt mehr PostgreSQL-Funktionen (z. B. COPY, LISTEN/NOTIFY, Arrays). Ich empfehle diesen. \n
Wir installieren pgx:
\ngo get github.com/jackc/pgx/v5\n\nJetzt schreiben wir Code, um eine Verbindung zur Datenbank herzustellen. Erstellen wir eine Datei main.go:
package main\n\nimport (\n "context"\n "fmt"\n "log"\n\n "github.com/jackc/pgx/v5/pgxpool"\n)\n\nfunc main() {\n // Verbindungs-URL: Benutzer, Passwort, Host, Port, Datenbankname\n dsn := "postgres://myuser:mypassword@localhost:5432/mydb?sslmode=disable"\n\n // Erstellen eines Verbindungspools\n pool, err := pgxpool.New(context.Background(), dsn)\n if err != nil {\n log.Fatalf("Pool konnte nicht erstellt werden: %v", err)\n }\n defer pool.Close()\n\n // Verbindung prüfen\n err = pool.Ping(context.Background())\n if err != nil {\n log.Fatalf("Verbindung fehlgeschlagen: %v", err)\n }\n\n fmt.Println("Erfolgreich mit PostgreSQL verbunden!")\n}\n\nBeachten Sie: Wir verwenden pgxpool, nicht eine einfache Verbindung. Ein Verbindungspool ist ein Must-have für die Produktion. Er ermöglicht die Wiederverwendung von Verbindungen und vermeidet den Overhead durch deren Erstellung und Schließung.
CRUD-Operationen: Erstellen, Lesen, Aktualisieren und Löschen
\n\nLassen Sie uns nun die klassischen Operationen mit der Tabelle users implementieren. Angenommen, wir haben die folgende Struktur:
type User struct {\n ID int\n Name string\n Age int\n}\n\n\nTabelle erstellen (Create)
\nEs ist besser, Migrationen mit separaten Tools durchzuführen, aber als Beispiel zeige ich, wie man raw SQL ausführt:
\nfunc createTable(ctx context.Context, pool *pgxpool.Pool) error {\n query := `\n CREATE TABLE IF NOT EXISTS users (\n id SERIAL PRIMARY KEY,\n name TEXT NOT NULL,\n age INT NOT NULL\n );\n `\n _, err := pool.Exec(ctx, query)\n return err\n}\n\n\nDatensatz hinzufügen (Insert)
\nWir verwenden QueryRow, um die generierte ID zurückzugeben:
func createUser(ctx context.Context, pool *pgxpool.Pool, user *User) error {\n query := `INSERT INTO users (name, age) VALUES ($1, $2) RETURNING id`\n err := pool.QueryRow(ctx, query, user.Name, user.Age).Scan(&user.ID)\n return err\n}\n\n\nDatensatz lesen (Select)
\nfunc getUserByID(ctx context.Context, pool *pgxpool.Pool, id int) (*User, error) {\n query := `SELECT id, name, age FROM users WHERE id = $1`\n user := &User{}\n err := pool.QueryRow(ctx, query, id).Scan(&user.ID, &user.Name, &user.Age)\n if err != nil {\n return nil, err\n }\n return user, nil\n}\n\n\n