Build a Simple GraphQL API in Go: Step‑by‑Step Tutorial

This tutorial shows how to wrap the jsonplaceholder REST service with a GraphQL layer in Go, covering data models, schema creation, resolver functions, server setup, and example queries with results.

360 Zhihui Cloud Developer
360 Zhihui Cloud Developer
360 Zhihui Cloud Developer
Build a Simple GraphQL API in Go: Step‑by‑Step Tutorial

Introduction

GraphQL is appearing in more and more projects. This article demonstrates how to wrap an existing REST API (jsonplaceholder) with a GraphQL layer using Go, focusing on practical implementation rather than theory.

Implementation

First, define the data models for posts and comments.

type Post struct {
    UserID int `json:"userId"`
    ID     int `json:"id"`
    Title  string `json:"title"`
    Body   string `json:"body"`
}

type Comment struct {
    PostID int    `json:"postId"`
    ID     int    `json:"id"`
    Name   string `json:"name"`
    Email  string `json:"email"`
    Body   string `json:"body"`
}

Helper functions fetchPostByID and fetchCommentsByPostID retrieve data from the REST endpoints and unmarshal the JSON into the structs.

Next, create the GraphQL query type, which exposes a single field post that accepts an id argument.

func createQueryType(postType *graphql.Object) graphql.ObjectConfig {
    return graphql.ObjectConfig{Name: "QueryType", Fields: graphql.Fields{
        "post": &graphql.Field{
            Type: postType,
            Args: graphql.FieldConfigArgument{"id": &graphql.ArgumentConfig{Type: graphql.NewNonNull(graphql.Int)}},
            Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                id := p.Args["id"]
                v, _ := id.(int)
                log.Printf("fetching post with id: %d", v)
                return fetchPostByID(v)
            },
        },
    }}
}

Define the Post GraphQL object, mapping struct fields and adding a comments field whose resolver fetches related comments.

func createPostType(commentType *graphql.Object) *graphql.Object {
    return graphql.NewObject(graphql.ObjectConfig{
        Name: "Post",
        Fields: graphql.Fields{
            "userId": &graphql.Field{Type: graphql.NewNonNull(graphql.Int)},
            "id":     &graphql.Field{Type: graphql.NewNonNull(graphql.Int)},
            "title":  &graphql.Field{Type: graphql.String},
            "body":   &graphql.Field{Type: graphql.String},
            "comments": &graphql.Field{
                Type: graphql.NewList(commentType),
                Resolve: func(p graphql.ResolveParams) (interface{}, error) {
                    post, _ := p.Source.(*Post)
                    log.Printf("fetching comments of post with id: %d", post.ID)
                    return fetchCommentsByPostID(post.ID)
                },
            },
        },
    })
}

Define the Comment GraphQL object, directly mapping the comment struct fields.

func createCommentType() *graphql.Object {
    return graphql.NewObject(graphql.ObjectConfig{
        Name: "Comment",
        Fields: graphql.Fields{
            "postId": &graphql.Field{Type: graphql.NewNonNull(graphql.Int)},
            "id":     &graphql.Field{Type: graphql.NewNonNull(graphql.Int)},
            "name":   &graphql.Field{Type: graphql.String},
            "email":  &graphql.Field{Type: graphql.String},
            "body":   &graphql.Field{Type: graphql.String},
        },
    })
}

Assemble the schema and start an HTTP server with the graphql-go-handler middleware.

func main() {
    schema, err := graphql.NewSchema(graphql.SchemaConfig{Query: graphql.NewObject(createQueryType(createPostType(createCommentType())) )})
    if err != nil {
        log.Fatalf("failed to create schema, error: %v", err)
    }
    handler := gqlhandler.New(&gqlhandler.Config{Schema: &schema})
    http.Handle("/graphql", handler)
    log.Println("Server started at http://localhost:3000/graphql")
    log.Fatal(http.ListenAndServe(":3000", nil))
}

After the server is running, you can query a post by ID and optionally request its comments using GraphiQL.

query {
  post(id: 5) {
    userId
    id
    title
    body
    comments {
      id
      email
      name
    }
  }
}

The response includes the post fields and, when requested, an array of comment objects.

{
  "data": {
    "post": {
      "userId": 1,
      "id": 5,
      "title": "...",
      "body": "...",
      "comments": [
        {"id": 21, "email": "...", "name": "..."},
        ...
      ]
    }
  }
}

Conclusion

This example shows how a simple Go layer can turn an existing REST API into a GraphQL service using the graphql-go library. The approach prioritises clarity, and readers are encouraged to adapt it to their own projects.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

APITutorialGraphQLgraphql-go
360 Zhihui Cloud Developer
Written by

360 Zhihui Cloud Developer

360 Zhihui Cloud is an enterprise open service platform that aims to "aggregate data value and empower an intelligent future," leveraging 360's extensive product and technology resources to deliver platform services to customers.

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.