Build a Simple GraphQL API Using Golang

Were going to see how to implement a web application using the Go programming language, but uses GraphQLwhen working with the data.

In case you’re not familiar, GraphQL is a technology for querying API data from a client-front end without having to make numerous requests or receiving unimportant data, both of which may cause negative affects on network latency.

Think of trying to query a relational database. Ideally you write a SQL query for the data you want and you do it in a single request. GraphQL tries to accomplish the same, but from an API consumption level.

We’re going to see how to implement a web application using the Go programming language, but uses GraphQLwhen working with the data.
. . .

Bootstrapping a Golang Application in Preparation for GraphQL Support

We’re going to assume that you have Go installed and configured. You don’t need to be a Go wizard to be successful with this tutorial, but it probably shouldn’t be your first time using it.

From the command line, execute the following to install our GraphQL project dependency:
go get github.com/graphql-go/graphql

More information about our dependency can be found on the project’s GitHub page.

Create a project somewhere in your $GOPATH and inside that project, create a file called main.go which will hold all of our application code. Within the main.go file, include the following code as a starting point:

In the above code we’re creating several Go data structures that will represent our data model in Go. We will also be creating a GraphQL data model, but it is important not to confuse the two as they are different. You’ll need both.

This particular application will be similar to iTunes. Let’s call it MyTunes. We’ll have information about albums, the songs that reside in them and the artists that perform them.

In the main function, we create a GraphQL schema, but for now we’re going to leave it without any information. Even though we’re not creating a RESTful API, that doesn’t mean we won’t need an API endpoint. With GraphQL we can send any and all queries to this single API endpoint and it will work its magic. The /graphql endpoint will accept requests that look like this:

curl -g 'http://localhost:12345/graphql?query={song{title,duration}}'

The important part of every request is the query property in the query parameters. This represents the GraphQL query that we’re sending to the server.

Before we get down and dirty with GraphQL, let’s come up with our mock data. Using a database is not the focus of this tutorial, so we don’t want to get hung up on those details.

Outside your main function, create the following:

We’ll keep it simple for now, but we’ve got two songs that are part of the Fearless album by Taylor Swift. At this point in time, we can do some preparation for querying with a GraphQL query.
. . .

Querying for Data with a GraphQL Query

We have the foundation of our application in place as well as a set of data to work with. Let’s try to query for that data, eventually with cURL or some other front-end application.

Remember when I mentioned the Go data structures were not our GraphQL data structures? Let’s create our GraphQL data structures.

In the main function of our application, add the following:

We can create a GraphQL object and define the fields or properties that exist in that object. Each field needs to have a type, where as in this case they are all strings. The same needs to apply for each of our models.

Take the GraphQL model for artists:

Finally, we can take a look at the model for each of our albums:

Yes, each of our fields in all three models are strings, but it isn’t really any different if you needed to change it to something else. Each of the GraphQL models were designed around the Go data structures. We can’t really work with the GraphQL models in Go like we can a native Go data structure.

The next GraphQL object we create will have a similar form, but will represent each of the possible queries we can perform. Having a model is meaningless unless we can apply it to some logic.

Take the rootQuery object, which has no specific or required name:

Every field that exists in this object will represent a possible query. We define a return type, in this case a list of songType and we provide a Resolve function that will be responsible for all of our driving logic.

When querying songs, we might want something like this for a Resolve function:
"songs": &graphql.Field{ Type: graphql.NewList(songType), Resolve: func(p graphql.ResolveParams) (interface{}, error) { return songs, nil }, },

Here is the final main.go looks like:

Notice that we have defined query to return songs, albums, and artists. Not its good time to test out graphql api.

First query the songs af follows, its should return all the songs:
curl -g 'http://localhost:12345/graphql?query={songs{title,duration}}'

{
"data":{
"songs":[
{
"duration":"4:01",
"title":"Fearless"
},
{
"duration":"4:54",
"title":"Fifteen"
}
]
}
}

Similarly you can Query the Albums & Artists as well. Give it a try:
curl -g 'http://localhost:12345/graphql?query={albums{id,year,artist}}'

{
"data":{
"albums":[
{
"artist":"1",
"id":"ts-fearless",
"year":"2008"
}
]
}
}

We’ve got querying down as of now. We could make things more complicated, but the strategy won’t really change. Now we can focus on altering data.
. . .

Create, Delete, and Update Data by using GraphQL for Mutations

GraphQL supports mutations as well as read-only queries. Both are no more difficult than the other and setup is more or less the same, which is convenient for us.

We’re going to create a new GraphQL object like we did for our queries. This object will hold all of our mutation queries. Start it off by doing the following:
rootMutation := graphql.NewObject(
graphql.ObjectConfig{
Name: "Mutation",
Fields: graphql.Fields{},
}
)

The naming doesn’t really matter. We’re going to hook it up to our schema like we did with the rootQuery object. Let’s create a mutation that will allow us to create a new song:

In the above example, we have a createSong field that returns a songType object. For input parameters, we’re expecting everything that composes our object. For the Resolve function, we are taking the data and adding it to the mock list of data.

Let’s wire it up to our schema:
schema,_: = graphql.NewSchema(graphql.SchemaConfig{
Query:rootQuery,
Mutation:rootMutation,
})

here is the final main.go with Query & Mutation looks like:
That wasn’t difficult was it?

Running a query that contains a mutation is really no more difficult than running a query that is read only. Take the following for example:
mutation { createSong(id: "7", album: "ts-fearless", title: "Breathe", duration: "4:23") { title, duration } }

You’ll notice that this particular query requires that we define it as a mutation. If we wanted to execute this query via a cURL command, it would look like the following:
curl -g 'http://localhost:12345/graphql?query=mutation+_{createSong(id:"7",album:"ts-fearless",title:"Breathe",duration:"4:23"){title,duration}}'

{
"data":{
"createSong":{
"duration":"4:23",
"title":"Breathe"
}
}
}

Not too bad right?

We could go ahead and create more mutations, but the process would be more or less the same, just as we saw with the other queries. There isn’t too much overhead with GraphQL.
. . .

Conclusion

You just saw how to get started with GraphQL in a Golang application. We didn’t use a database for this example, but we saw how to create a data model, query it, and manipulate data via some kind of GraphQL mutation.

On a mission to build Next-Gen Community Platform for Developers