Simple Golang + Mux Router API Service
Published: 2020-12-22 17:35:22

Maybe you want to create a simple Golang REST API, to test the language out. This tutorial aims to build a simple API Service that returns a hardcoded json using the Mux Router library

### Objectives

Create a simple API on a port that returns a `{ "hello": "world" }` JSON

### Setting up libraries and `main.go`

1. Start by setting up the go modules

```sh
go mod init simple-backend
go get github.com/gorilla/mux # this is the mux library
```

2. Set up `main.go`

```go
// main.go
package main

func main() {
  // to be filled later
}
```



Your project folder structure should now look like this:
```
.
├── go.mod
├── go.sum
└── main.go
```

### Setting up `app.go`

We set up the `app.go` to house all the app's main logic, e.g. `app.run()` and `app.initialiseRoutes()` methods.

1. Add `app.go` on the root directory level:

```
.
├── app.go # add here
├── go.mod
├── go.sum
└── main.go
```

2. Add the `App` type, which houses the mux router, and add the relevant methods `run()` and `initialiseRoutes()`

```go
// app.go
package main

import (
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

// App export
type App struct {
	Router *mux.Router
}

// TODO: add handlers here

func (app *App) initialiseRoutes() {
  app.Router = mux.NewRouter()
  // TODO: add routes here
}

func (app *App) run() {
	log.Fatal(http.ListenAndServe(":8080", app.Router))
}

```

We have a few `TODO`'s to complete. Lets start by adding the handler and some helper functions for future use.

That being said, when the number of handlers grow, we will have to find a new folder for them to be in. For now though app.go should do just fine.

```go
// TODO: add handlers here
func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
	var response map[string]interface{}
	json.Unmarshal([]byte(`{ "hello": "world" }`), &response)
	respondWithJSON(w, http.StatusOK, response)
}

func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	json.NewEncoder(w).Encode(payload)
}
```

Here the handler's function signature should match 

`func handlerFunc(w http.ResponseWriter, r *http.Request)`

at least that is what the 

`mux.Router.HandleFunc(path, handlerFunc)` 

expects anyway.


On the other hand, the `respondWithJSON()` function helps us pass any struct over to the `http.responseWriter` to be sent back to the client. Anyway, for future handlers we decide to implement, we can always reuse this helper function to feed the structs back to the client.

3. Finish up the `initialiseRoutes()` to use the handler function

Inside the `initialiseRoutes()` function, we add the routes.

```go
func (app *App) initialiseRoutes() {
	app.Router = mux.NewRouter()
  // TODO: add routes here
	app.Router.HandleFunc("/", helloWorldHandler)
}
```

We could add a few routes here as we wish, but here we add the `helloWorldHandler` to the path `/` so that the request `localhost:8080` would be routed to the `helloWorldHandler`


The **app.go** should end up like below:
```go
// app.go
package main

import (
	"encoding/json"
	"log"
	"net/http"

	"github.com/gorilla/mux"
)

// App export
type App struct {
	Router *mux.Router
}

func helloWorldHandler(w http.ResponseWriter, r *http.Request) {
	var response map[string]interface{}
	json.Unmarshal([]byte(`{ "hello": "world" }`), &response)
	respondWithJSON(w, http.StatusOK, response)
}

func respondWithJSON(w http.ResponseWriter, code int, payload interface{}) {
	w.Header().Set("Content-Type", "application/json")
	w.WriteHeader(code)
	json.NewEncoder(w).Encode(payload)
}

func (app *App) initialiseRoutes() {
	app.Router = mux.NewRouter()
	app.Router.HandleFunc("/", helloWorldHandler)
}

func (app *App) run() {
	log.Fatal(http.ListenAndServe(":8080", app.Router))
}

```

### Finish up `main.go`

1. Here we finish up our **main.go**, adding the `run()` and the `initialiseRoutes()` to the entrace function

The **main.go** should end up like so:

```go
// main.go
package main

func main() {
	app := App{}
	app.initialiseRoutes()
	app.run()
}
```

### Start the server

...and we should be good to go! Now run the below command to start the server from the project root directory:

```
go run .
```

or, you can build an executable and run it

```
go build 
./simple-backend # don't forget to put this inside your .gitignore!
```

and, you can test the server using 

```
curl localhost:8080
{"hello":"world"}
```



## Conclusion

...and there you have it! A simple Golang API server using the Mux router library. 

However, in an actual application, the functionality would not be as simple as returning a mere "hello world" response. Next time, we will be improving on this project, tidying up the folder structure and adding more functionality to it.