Einleitung: Warum GraphQL und Go das ideale Paar sind
Moderne Webentwicklung erfordert flexible und leistungsstarke APIs. REST-APIs leiden trotz ihrer Beliebtheit oft unter Datenüberladung (over-fetching) oder Datenmangel (under-fetching). GraphQL löst dieses Problem, indem es dem Client ermöglicht, genau das anzufragen, was benötigt wird. Und Go (Golang) wird mit seiner Geschwindigkeit, Einfachheit und integrierten Unterstützung für Nebenläufigkeit zur idealen Sprache für die Erstellung von GraphQL-Servern.
In diesem Tutorial erstellen wir Schritt für Schritt eine vollständige GraphQL-API in Go. Sie lernen, wie Sie einen Server einrichten, ein Schema definieren, Resolver schreiben sowie Abfragen (queries) und Mutationen (mutations) implementieren. Am Ende des Artikels haben Sie eine funktionierende API, die zur Integration mit jedem Client bereit ist.
Schritt 1: Projekteinrichtung und Installation der Abhängigkeiten
Zunächst erstellen wir ein neues Go-Modul und installieren die erforderlichen Bibliotheken. Wir werden zwei beliebte GraphQL-Bibliotheken verwenden: graphql-go und graphql-go-handler.
1.1. Modul initialisieren
go mod init graphql-tutorial
1.2. Bibliotheken installieren
go get github.com/graphql-go/graphqlgo get github.com/graphql-go/handler
Diese Bibliotheken bieten alle notwendigen Werkzeuge für die Arbeit mit Schemata, Typen und Resolvern.
Schritt 2: Erstellen eines grundlegenden GraphQL-Schemas
Das Schema ist das Herzstück einer GraphQL-API. Es definiert, welche Daten abgerufen und welche Aktionen ausgeführt werden können. Beginnen wir mit einem einfachen Modell "Benutzer".
2.1. Definition des User-Typs
import "github.com/graphql-go/graphql"
var userType = graphql.NewObject(graphql.ObjectConfig{ Name: "User", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "email": &graphql.Field{ Type: graphql.String, }, },})
2.2. Erstellen der Root-Abfrage
var rootQuery = graphql.NewObject(graphql.ObjectConfig{ Name: "RootQuery", Fields: graphql.Fields{ "user": &graphql.Field{ Type: userType, Args: graphql.FieldConfigArgument{ "id": &graphql.ArgumentConfig{ Type: graphql.Int, }, }, Resolve: func(p graphql.ResolveParams) (interface{}, error) { id, _ := p.Args["id"].(int) // Hier kommt die Logik zum Abrufen des Benutzers aus der DB return getUserByID(id), nil }, }, },})
2.3. Zusammenführen zum Schema
var schema, _ = graphql.NewSchema(graphql.SchemaConfig{ Query: rootQuery,})
Schritt 3: Implementierung von Resolvern und Server
Nachdem das Schema fertig ist, müssen die Resolver geschrieben werden – die Funktionen, die tatsächlich die Daten zurückgeben. Der Einfachheit halber verwenden wir einen In-Memory-Speicher.
3.1. In-Memory-Speicher
type User struct { ID int `json:"id"` Name string `json:"name"` Email string `json:"email"`}
var users = []User{ {ID: 1, Name: "Ivan Petrov", Email: "ivan@example.com"}, {ID: 2, Name: "Maria Sidorova", Email: "maria@example.com"},}
func getUserByID(id int) *User { for _, u := range users { if u.ID == id { return &u } } return nil}
3.2. Starten des HTTP-Servers
package main
import ( "fmt" "log" "net/http"
"github.com/graphql-go/handler")
func main() { h := handler.New(&handler.Config{ Schema: &schema, Pretty: true, GraphiQL: true, // Integrierte IDE aktivieren })
http.Handle("/graphql", h) fmt.Println("Server gestartet auf")