So over this past weekend, I decided to build a sync client between my private WordPress instance that powers the content on this site, and my other hosted blogs on Hashnode and Instead of using the standard REST API to get the data, I figure why not try to hit the GraphQL endpoint. Here are some of my findings.

For the demo code in this article, I’ll be using Hashnodes GraphQL API since it’s open and pretty simple to use.

Setting up the project

I’m going to start a new project by running the following commands in the VSCode terminal. This will initialize the project, install the necessary module, and create the main.go file.

go mod init go-graphql-demo
go get
touch main.go

Next, I’ll update the main.go file with the following. This sets up the main func and creates the GraphQL client necessary to pull data.

package main

import ""

func main() {
    client := graphql.NewClient("")

Querying data

Before we can pull data down, we’ll need to create a struct to hold the data. Running the following query in the Hashnode GraphQL UI shows us what the data looks like.

I'll add this struct to the bottom of the file to hold the data. I'm defining the child structs inline for the sake of the demo, but creating them separately will do the same and would probably result in cleaner code.

type QueryUserResponse struct {
    User struct {
        Publication struct {
            Posts []struct {
                Id        stringjson:"_id"
                Title     string
                dateAdded string

Now let’s create a separate func to run the query. Note how you need to pass a reference of the struct into the Run method, similar to how you would unmarshal JSON. I’ll iterate through the results and log them out as well, just to see it working.

func queryData(client *graphql.Client) {
    query := `
        user(username:"brianmmdev") {
            publication {
                posts {
    request := graphql.NewRequest(query)
    var response QueryUserResponse
    err := client.Run(context.Background(), request, &response)
    if err != nil {

    for _, el := range response.User.Publication.Posts {

I updated the main method to call queryData. Running the code results in the following from the console.

You can find the source code for this post at