
Hallo allerseits! Es gibt viele Artikel über GraphQL auf Habr, aber nachdem ich sie durchgesehen hatte, stellte ich fest, dass sie alle eine so wunderbare Sprache wie Go umgehen. Heute werde ich versuchen, dieses Missverständnis zu korrigieren. Dazu schreiben wir eine API auf Go mit GraphQL.
Kurz gesagt: GraphQL ist eine Abfragesprache zum Erstellen einer API, die beschreibt, in welcher Form Daten angefordert und zurückgegeben werden sollen (detailliertere Informationen zur offiziellen Ressource graphql.imtqy.com und zum Hub ).
Sie können argumentieren, dass GraphQL oder REST hier besser ist.
Wir werden die klassische API haben: CRUD (Erstellen, Lesen, Aktualisieren, Löschen) Hinzufügen, Empfangen, Bearbeiten und Löschen von Produkten im Online-Shop.
Auf der Serverseite werden wir die fertige Implementierung von GraphQL graphql-go verwenden
Zuerst müssen Sie graphql-go herunterladen, dies kann mit dem Befehl erfolgen
go get github.com/graphql-go/graphql
Als nächstes beschreiben wir die Struktur des Produkts (in vereinfachter Form)
type Product struct { ID int64 `json:"id"` Name string `json:"name"` Info string `json:"info,omitempty"` Price float64 `json:"price"` }
ID
- eindeutige Kennung, Name
- Name, Info
- Produktinformationen, Price
- Preis
Als erstes müssen Sie die Do
Methode aufrufen, die ein Datenschema und Abfrageparameter als Eingabeparameter akzeptiert. Die resultierenden Daten werden an uns zurückgesandt (zur weiteren Übermittlung an den Kunden).
result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, })
Vollständiger Code func executeQuery(query string, schema graphql.Schema) *graphql.Result { result := graphql.Do(graphql.Params{ Schema: schema, RequestString: query, }) if len(result.Errors) > 0 { fmt.Printf("errors: %v", result.Errors) } return result } func main() { http.HandleFunc("/product", func(w http.ResponseWriter, r *http.Request) { result := executeQuery(r.URL.Query().Get("query"), schema) json.NewEncoder(w).Encode(result) }) http.ListenAndServe(":8080", nil) }
Schema
- Datenschema, RequestString
- Wert des RequestString
, in unserem Fall query
Schema
Ein Schema akzeptiert zwei Stammdatentypen: Query
- unveränderliche Daten, Mutation
- veränderbare Daten
var schema, _ = graphql.NewSchema( graphql.SchemaConfig{ Query: queryType, Mutation: mutationType, }, )
Abfrage
Query
wird zum Lesen (und nur zum Lesen) von Daten verwendet. Mit Query
legen wir fest, welche Daten der Server zurückgeben soll.
Wir werden eine Implementierung des Query
schreiben. In unserem Fall enthält sie Felder mit Informationen zu einem einzelnen Produkt (Produkt) und einer Warenliste (Liste).
var queryType = graphql.NewObject( graphql.ObjectConfig{ Name: "Query", Fields: graphql.Fields{ "product": &graphql.Field{ Type: productType, Description: "Get product by id",
Der Typ queryType enthält den erforderlichen Name
und die erforderlichen Fields
sowie die optionale Description
(zur Dokumentation verwendet).
Das Feld Fields
enthält wiederum das erforderliche Feld Type
und die optionalen Args
, Resolve
und Description
Argumente (Argumente)
Argumente - Eine Liste von Parametern, die vom Client auf den Server übertragen werden und sich auf das Ergebnis der zurückgegebenen Daten auswirken. Argumente sind an ein bestimmtes Feld gebunden. Die Argumente können sowohl in Query
als auch in Mutation
.
?query={product(id:1){name,info,price}}
In diesem Fall gibt das id
Argument für das product
mit dem Wert 1 an, dass das Produkt mit dem angegebenen Bezeichner zurückgegeben werden muss.
Für die list
Argumente weggelassen, aber in einer realen Anwendung können dies beispielsweise sein: limit
und offset
.
Auflösen (Anerkennung)
Die gesamte Logik für die Arbeit mit Daten (z. B. Datenbankabfragen, Verarbeitung und Filterung) liegt in den Erkennern. Sie geben die Daten zurück, die als Antwort auf die Anforderung an den Client übertragen werden.
Typ
GraphQL verwendet sein Typsystem zur Beschreibung von Daten. Sie können sowohl die Grundtypen String
, Int
, Float
, Boolean
als auch Ihre eigenen (benutzerdefinierten) Typen verwenden. Für unser Beispiel benötigen wir einen benutzerdefinierten Product
, der alle Eigenschaften des Produkts beschreibt
var productType = graphql.NewObject( graphql.ObjectConfig{ Name: "Product", Fields: graphql.Fields{ "id": &graphql.Field{ Type: graphql.Int, }, "name": &graphql.Field{ Type: graphql.String, }, "info": &graphql.Field{ Type: graphql.String, }, "price": &graphql.Field{ Type: graphql.Float, }, }, }, )
Für jedes Feld wird der Basistyp angegeben, in diesem Fall graphql.Int
, graphql.String
, graphql.Float
.
Die Anzahl der verschachtelten Felder ist nicht begrenzt, sodass Sie ein Diagrammsystem jeder Ebene implementieren können.
Mutation
Mutationen sind diese veränderlichen Daten, die Folgendes umfassen: Hinzufügen, Bearbeiten und Löschen. Ansonsten sind Mutationen regulären Abfragen sehr ähnlich: Sie verwenden auch Args
Argumente und geben Resolve
Daten als Antwort auf die Abfrage zurück.
Schreiben wir Mutationen für unsere Produkte. var mutationType = graphql.NewObject(graphql.ObjectConfig{ Name: "Mutation", Fields: graphql.Fields{ "create": &graphql.Field{ Type: productType, Description: "Create new product", Args: graphql.FieldConfigArgument{ "name": &graphql.ArgumentConfig{ Type: graphql.NewNonNull(graphql.String),
Alles ähnlich wie queryType
. Es gibt nur einen kleinen Feature-Typ graphql.NewNonNull(graphql.Int)
, der besagt, dass dieses Feld nicht leer sein darf (ähnlich wie NOT NULL
in MySQL).
Das ist alles. Jetzt haben wir eine einfache Go CRUD-API für die Arbeit mit Waren. Wir haben die Datenbank für dieses Beispiel nicht verwendet, aber wir haben uns angesehen, wie ein Datenmodell erstellt und mithilfe von Mutationen bearbeitet wird.
Beispiele
Wenn Sie die Quelle über heruntergeladen haben
go get github.com/graphql-go/graphql
Gehen Sie einfach mit einem Beispiel in das Verzeichnis
cd examples/crud
und führen Sie die Anwendung aus
go run main.go
Sie können die folgenden Abfragen verwenden:
Produkt per ID abrufen
http://localhost:8080/product?query={product(id:1){name,info,price}}
Eine Liste der Produkte erhalten
http://localhost:8080/product?query={list{id,name,info,price}}
Neues Produkt hinzufügen
http://localhost:8080/product?query=mutation+_{create(name:"Tequila",info:"Strong alcoholic beverage",price:999){id,name,info,price}}
Produktbearbeitung
http://localhost:8080/product?query=mutation+_{update(id:1,price:195){id,name,info,price}}
Produkt nach ID entfernen
http://localhost:8080/product?query=mutation+_{delete(id:1){id,name,info,price}}
Wenn Sie REST verwenden, achten Sie auf GraphQL als mögliche Alternative. Ja, auf den ersten Blick scheint es schwieriger zu sein, aber es lohnt sich zu beginnen und in ein paar Tagen werden Sie diese Technologie beherrschen. Zumindest wird es nützlich sein.