Create A Simple RESTful API With Golang

Most modern applications have separation between the backend and the frontend layers.  The backend is typically a RESTful API and is critical part of full stack development.  These APIs are generally further broken down into a collection of routes, often referred to as endpoints.  Building applications like this is often very clean and maintainable in comparison to mashing everything into a single application.

I have been creating RESTful APIs with a variety of programming languages, for example Node.js and Java, but lately I’ve been doing a lot of research on the Go programming language.  It is fast and very solid programming language that every seems to be talking about.  Because of this it only made sense to see what it took to build a RESTful API with Go, often referred to as GoLang.

We’re going to see what it takes to build a simple API that does basic CRUD operations using the Go programming language.

For simplicity, we’re not going to be using a database in this example.  We’re going to be hard-coding some data which can be referred to as mock data.  This will allow us to focus on core material like defining endpoints and doing basic operations.

At this point we’re going to assume Go is already installed and configured on your machine.  From the Terminal (Mac and Linux) or Command Prompt (Windows), execute the following:

If your command line doesn’t support any of the above, just manually create the directory any way you see fit.

In the freshly created project, you’ll want to create a file that contains our main function.  In this example we’ll be using $GOPATH/src/github.com/nraboy/restapi/myproject.go.

Inside this GoLang file we want to add the following code.  It is a lot of code, but don’t worry, we’re going to break it down next.

So what is happening in the above code?

The first thing you’ll notice is that we’re importing various dependencies.  We’ll be working with JSON data so the encoding/json dependency is required.  While we’ll be working with HTTP requests, the net/http dependency is not quite enough.  The mux dependency is a helper to not only make endpoints easier to create, but also give us more features.  Since this is an external dependency, it must be downloaded like follows:

More information on mux can be found in the official documentation.

With the dependencies imported we want to create the struct objects that will house our data.  The data we plan to store will be people data:

You’ll notice we are defining what properties exist in the struct, but we are also defining tags that describe how the struct will appear as JSON.  Inside each of the tags there is an omitempty parameter.  This means that if the property is null, it will be excluded from the JSON data rather than showing up as an empty string or value.

Inside the Person struct there is an Address property that is a pointer.  This will represent a nested JSON object and it must be a pointer otherwise the omitempty will fail to work.  So what does Address look like?

Again, this is a nested structure that is not too different from the previous.

Because we’re not using a database, we want to create a public variable that is global to the project.  This variable will be a slice of Person and contain all the data used in this application.

Our easiest endpoint is probably the GetPeopleEndpoint because it will only return the full person variable to the frontend.  Where things start to change is when we want to insert, delete, or get a particular record.

In the above GetPersonEndpoint we are trying to get a single record.  Using the mux library we can get any parameters that were passed in with the request.  We then loop over our global slice and look for any ids that match the id found in the request parameters.  If a match is found, use the JSON encoder to display it, otherwise create an empty JSON object.

In reality, your endpoints will communicate with a database and will probably involve a lot less application logic.  This is because you’ll be using some form of querying instead.

The CreatePersonEndpoint is a bit different because we’ll be receiving JSON data to work with in the request.

In the above we decode the JSON data that was passed in and store it in a Person object.  We assign the new object an id based on what mux found and then we append it to our global slice.  In the end, our global array will be returned and it should include everything including our newly added piece of data.

In the scenario of this example application, the method for deleting data is a bit different as well.

In this case, we have the DeletePersonEndpoint looping through the data similarly to the GetPersonEndpoint we saw earlier.  The difference is that instead of printing the data, we need to remove it.  When the id to be deleted has been found, we can recreate our slice with all data excluding that found at the index.

Finally we end up in our runnable main function that brings the application together.

In the above code we first create our new router and add two objects to our slice to get things started.  Next up we have to create each of the endpoints that will call our endpoint functions.  Notice we are using GETPOST, and DELETE where appropriate.  We are also defining parameters that can be passed in.

At the very end we define that our server will run on port 12345, which at this point brings our project to a close.  Run the project and give it a shot.  You might need a tool like Postman or cURL to test all the endpoints.

Conclusion

You just saw how to build a very simple RESTful API using the Go programming language.  While we used mock data instead of a database, we saw how to create endpoints that do various operations with JSON data and GoLang slices.  By creating an API your application will become easy to maintain and be expandable to web, mobile and IoT as each of these platforms will only require a different frontend that we had not created in this example.

A video version of this article can be seen below.

Nic Raboy

Nic Raboy is an advocate of modern web and mobile development technologies. He has experience in Java, JavaScript, Golang and a variety of frameworks such as Angular, NativeScript, and Apache Cordova. Nic writes about his development experiences related to making web and mobile development easier to understand.

  • Eric

    how do I run the api?What is the web address to check , if its running?

    • Well you would build it using ‘go build’ and then you would run the binary file. The application will serve on localhost:12345 and you can use any of the endpoints listed in the tutorial.

      Best,

      • Eric

        Hi Nic,
        I am completely new to GO programming. This is my first program and I am trying to build an API for a quiz. I am using Atom as an editor and compiled it using command prompt. It compiles successfully and gives me firewall blocking message. After allowing access to firewall message, nothing happens. I even tried pasting http://localhost: 12345 in browser, but it turns into 404 error.

        I have limited knowledge and would really appreciate the if you provide me steps to run the api and check ifits working.

        Thanks!!

  • swati gupta

    How do we document this api? I installed swagger UI package but I dont know how to generate swagger specification ( which is required to get Swagger UI) automatically. Could you please suggest?

    Thanks!!

    • I’ve never used Swagger, sorry.

  • Randy Fay

    Thanks very much for this. I made some small improvements and put it up on https://github.com/rfay/go_restapi_example – Mostly just used a map for people instead of an array that was allowing duplicates.

  • SBlangkon

    I’m new learning Go and this article helpful.

  • andrei

    Hey friend. I’m very new to golang, maybe you can help me out. I want to create the following router: /users/:id, /users/autocomplete. The problem is that the /autocomplete route is not interpreted as a new route. The routers sees ‘autocomplete’ as the id of the user. Is there any way I can bypass that ? Thanks

    • Try adding a slash at the end so it treats it like a path rather than a variable.

  • tmack8080

    Hi Nic,

    Any plans to blog about consuming REST APIs using Golang? I work in DevOps and need to consume vendor APIs. For example, how can Golang be used to consume FreeNAS APIs? Say I wanted to get all the volumes out of the array …

    Thanks

    • I’ll see what I can cook up. Stay tuned 🙂

  • distra vantari

    I’m really new to golang, is there any way to test it on postman but use x-www-form-urlencoded instead of raw? I tried to do it but it’s not working. This article really help me a lot btw, thank you

    • If you send form data you need to receive it as such. It is better practice for an API to handle JSON requests like I demonstrated.

  • Emmanuel Kobby

    can you do a simple one with mysql

  • Ahmed Farag

    Thanks This is very helpful