Введение: Why GraphQL and Go are the Perfect Pair
Modern web development requires flexible and high-performance APIs. REST API, despite its popularity, often suffers from over-fetching or under-fetching of data. GraphQL solves this problem by allowing the client to request exactly what is needed. And Go (Golang) with its speed, simplicity, and built-in concurrency support becomes the ideal language for building GraphQL servers.
In this tutorial, we will step by step create a full-featured GraphQL API in Go. You will learn how to set up a server, define a schema, write resolvers, and implement queries and mutations. By the end of the article, you will have a working API ready for integration with any client.
Step 1: Project Setup and Dependency Installation
First, let's create a new Go module and install the necessary libraries. We will use two popular GraphQL libraries: graphql-go and graphql-go-handler.
1.1. Module Initialization
go mod init graphql-tutorial1.2. Library Installation
go get github.com/graphql-go/graphqlgo get github.com/graphql-go/handlerThese libraries provide all the necessary tools for working with schemas, types, and resolvers.
Step 2: Creating a Basic GraphQL Schema
The schema is the heart of a GraphQL API. It defines what data can be retrieved and what actions can be performed. Let's start with a simple "User" model.
2.1. Defining the User Type
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. Creating the Root Query
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) // Here will be the logic for getting the user from the DB return getUserByID(id), nil }, }, },})2.3. Combining into a Schema
var schema, _ = graphql.NewSchema(graphql.SchemaConfig{ Query: rootQuery,})Step 3: Implementing Resolvers and the Server
Now that the schema is ready, we need to write resolvers — functions that actually return data. For simplicity, we'll use an in-memory store.
3.1. In-memory Store
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. Starting the HTTP Server
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, // Enable built-in IDE })
http.Handle("/graphql", h) fmt.Println("Server started on")