Simple Golang + Mux Router API Service
Tags: Golang, Beginner, API

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

P.S. it looks nicer here! at https://dev.to/mecode4food/simple-golang-mux-router-api-service-3nal

Objectives

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

Setting up libraries and main.go

Start by setting up the go modules

go mod init simple-backend

go get github.com/gorilla/mux # this is the mux library

2. Set up main.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.

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()

// 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.

// 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.

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:

// 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

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:

// 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.