3 Getting to Know graphql-go: A GraphQL Library for Go
Getting to Know graphql-go: A GraphQL Library for Go
GraphQL has revolutionized the way developers build APIs over the past few years. With its declarative approach and flexible queries, GraphQL has become a popular choice to replace REST, and the Go (Golang) ecosystem is no exception. One of the leading GraphQL implementations in Golang is graphql-go
, a simple yet powerful library for building GraphQL servers.
In this article, I’ll cover what graphql-go is, why you should consider it when building APIs in Go, along with an implementation example, query simulations, and even a visualization of the GraphQL request flow using mermaid code.
What is graphql-go?
graphql-go is an open source library developed by the Go community, inspired by the primary GraphQL implementation in the JavaScript ecosystem (graphql-js). This library provides tools to define schemas, set up resolvers, and process GraphQL queries safely and quickly on a Go backend.
Some of the advantages of graphql-go:
- Type-safe schema: The schema is defined explicitly using Go structs and field tags.
- Simple resolvers: Resolver functions can access data easily, with support for context and arguments.
- HTTP integration: A great fit for integrating directly with
net/http. - Performance and scalability: Very fast and efficient, ideal for real-time and scale-up applications.
- Middleware support: Easy to integrate with other Go middleware (e.g. logging, auth, tracer).
Why Choose graphql-go?
As engineers, choosing tools isn’t just about following trends — it’s about how well a tool supports our application’s needs, both now and going forward. Here are some reasons to choose graphql-go:
| Criteria | graphql-go | REST (using Gorilla Mux, etc.) |
|---|---|---|
| Flexibility | Queries can filter, sort, and aggregate all at once. Clients fetch only the data they need. | Rigid responses and varying endpoints |
| Typing | Go-based schema and resolvers are type-safe, ideal for strictly typed codebases. | Generally not strict, depends on JSON |
| Ecosystem | Many complementary libraries (validation, auth, dataloader). | More mature, plenty of examples. |
| Learning Curve | Challenging at first, but well documented. | Relatively easy, with many tutorials. |
| Performance | Fast! Used by large streaming companies, banks, and fintechs. | Proven and reliable. |
A Simple graphql-go API Implementation Example
We’ll practice building a simple GraphQL API for a library application. The endpoint can query a list of books and add new ones.
1. Installing the Dependency
1go get github.com/graph-gophers/graphql-go
2go get github.com/graph-gophers/graphql-go/relay2. Define the GraphQL Schema
Create a schema.graphql file:
1type Book {
2 id: ID!
3 title: String!
4 author: String!
5}
6
7type Query {
8 books: [Book!]!
9}
10
11type Mutation {
12 createBook(title: String!, author: String!): Book!
13}3. Map the Schema to Go Structs
Create a schema.go file:
1package main
2
3import (
4 "context"
5 "github.com/graph-gophers/graphql-go"
6)
7
8type Book struct {
9 ID graphql.ID
10 Title string
11 Author string
12}
13
14type Resolver struct {
15 books []*Book
16}
17
18func (r *Resolver) Books(ctx context.Context) ([]*Book, error) {
19 return r.books, nil
20}
21
22type mutationResolver struct{ resolver *Resolver }
23
24func (m *mutationResolver) CreateBook(ctx context.Context, args struct{ Title, Author string }) (*Book, error) {
25 book := &Book{
26 ID: graphql.ID(fmt.Sprintf("B%d", len(m.resolver.books)+1)),
27 Title: args.Title,
28 Author: args.Author,
29 }
30 m.resolver.books = append(m.resolver.books, book)
31 return book, nil
32}4. Initialize the Schema & Run the HTTP Server
Create a main.go file:
1package main
2
3import (
4 "fmt"
5 "io/ioutil"
6 "log"
7 "net/http"
8
9 "github.com/graph-gophers/graphql-go"
10 "github.com/graph-gophers/graphql-go/relay"
11)
12
13func main() {
14 schemaBytes, err := ioutil.ReadFile("schema.graphql")
15 if err != nil {
16 log.Fatal(err)
17 }
18 resolver := &Resolver{books: []*Book{
19 {ID: "B1", Title: "Golang for Beginners", Author: "John Doe"},
20 }}
21 schema := graphql.MustParseSchema(string(schemaBytes), resolver)
22 http.Handle("/query", &relay.Handler{Schema: schema})
23
24 log.Println("connect to http://localhost:8080/query for GraphQL playground")
25 log.Fatal(http.ListenAndServe(":8080", nil))
26}Query & Mutation Simulation
Let’s test the GraphQL API using tools like GraphQL Playground or curl:
Query the List of Books
1query {
2 books {
3 id
4 title
5 author
6 }
7}Response:
1{
2 "data": {
3 "books": [
4 {
5 "id": "B1",
6 "title": "Golang for Beginners",
7 "author": "John Doe"
8 }
9 ]
10 }
11}Adding a New Book
1mutation {
2 createBook(title: "Machine Learning with Go", author: "Jane Smith") {
3 id
4 title
5 author
6 }
7}Response:
1{
2 "data": {
3 "createBook": {
4 "id": "B2",
5 "title": "Machine Learning with Go",
6 "author": "Jane Smith"
7 }
8 }
9}GraphQL Flow Diagram in graphql-go
The mermaid visualization below illustrates the GraphQL request flow on the server we just built:
flowchart TD
A[Client] -- HTTP POST /query --> B[Go HTTP router]
B -- kirim payload ke relay.Handler --> C[graphql-go ParseSchema]
C -- Temukan Query / Mutation --> D[Resolver Function]
D -- Akses Data (slice, DB, atau API) --> E[Tulis Response JSON]
E -- Response JSON --> A
Development Tips and Best Practices
Use Context for Auth and Tracing Note that every resolver receives a
context.Context. Use it to inject user info (JWT claims), set timeouts, and monitor request traces.Test Resolvers Independently Since the schema and resolvers are separate, you can unit test each resolver (for example, by mocking data to a database).
Middleware Integration Integrate with popular Go middleware, such as logging, rate limiters, and metrics.
Schema-First or Code-First With
graphql-go, you can start from a schema file (*.graphql) or generate the schema from Go structs. Choose whichever suits your team.
Conclusion
graphql-go brings flexibility, performance, and simplicity to building GraphQL APIs within the Go ecosystem. With a type-safe schema, easy mapping between structs and the schema, and smooth integration with HTTP and middleware, this library is a great fit for modern microservices and real-time backends.
If you need a flexible and powerful API, consider graphql-go as the foundation for your next API layer. Learn and explore further in the graphql-go repository, and build a scalable API for the future!
References: