Search icon CANCEL
Subscription
0
Cart icon
Your Cart (0 item)
Close icon
You have no products in your basket yet
Save more on your purchases now! discount-offer-chevron-icon
Savings automatically calculated. No voucher code required.
Arrow left icon
Explore Products
Best Sellers
New Releases
Books
Videos
Audiobooks
Learning Hub
Conferences
Free Learning
Arrow right icon
Arrow up icon
GO TO TOP
Hands-On RESTful Web Services with Go

You're reading from   Hands-On RESTful Web Services with Go Develop elegant RESTful APIs with Golang for microservices and the cloud

Arrow left icon
Product type Paperback
Published in Feb 2020
Publisher Packt
ISBN-13 9781838643577
Length 404 pages
Edition 2nd Edition
Languages
Arrow right icon
Author (1):
Arrow left icon
Naren Yellavula Naren Yellavula
Author Profile Icon Naren Yellavula
Naren Yellavula
Arrow right icon
View More author details
Toc

Table of Contents (16) Chapters Close

Preface 1. Getting Started with REST API Development 2. Handling Routing for our REST Services FREE CHAPTER 3. Working with Middleware and RPC 4. Simplifying RESTful Services with Popular Go Frameworks 5. Working with MongoDB and Go to Create a REST API 6. Working with Protocol Buffers and gRPC 7. Working with PostgreSQL, JSON, and Go 8. Building a REST API Client in Go 9. Asynchronous API Design 10. GraphQL and Go 11. Scaling our REST API Using Microservices 12. Containerizing REST Services for Deployment 13. Deploying REST Services on Amazon Web Services 14. Handling Authentication for our REST Services 15. Other Books You May Enjoy

ServeMux – a basic router in Go

ServeMux is an HTTP request multiplexer. The HandleFunc we used in the preceding section is actually a method of ServeMux. By using ServeMux, we can handle multiple routes. We can also create our own multiplexer. A multiplexer handles the logic of separating routes with a function called ServeHTTP. So, if we create a Go struct with the ServeHTTP method, it can do the job as the in-built multiplexer.

Consider a route as a key in a Go dictionary (map) and a multiplexer as its value. Go finds the multiplexer from the route and tries to execute the ServeHTTP function. In the following section, we will see the usage of ServeMux by creating an API that generates UUID strings.

Developing a UUID generation API using ServeMux

A UUID is a unique identifier for a resource or a transaction. UUIDs are widely used for identifying an HTTP request. Let us develop an API for generating a UUID. Please follow these steps:

  1. Create the program file as follows:
touch -p $GOPATH/src/github.com/git-user/chapter2/uuidGenerator/main.go
  1. Any Go struct with a few dedicated HTTP methods is qualified to be a ServeMux. For example, we can create a custom UUID struct and implement the ServeHTTP function in order to make it a ServeMux object. Following is the implementation for the uuidGenerator.go module:
import (
"crypto/rand"
"fmt"
)

// UUID is a custom multiplexer
type UUID struct {
}

func (p *UUID) ServeHTTP(w http.ResponseWriter, r *http.Request) {
if r.URL.Path == "/" {
giveRandomUUID(w, r)
return
}
http.NotFound(w, r)
return
}

func giveRandomUUID(w http.ResponseWriter, r *http.Request) {
c := 10
b := make([]byte, c)
_, err := rand.Read(b)
if err != nil {
panic(err)
}
fmt.Fprintf(w, fmt.Sprintf("%x", b))
}

It consists of the UUID struct that acts as a ServeMux object. We can access the URL path in the handler function and use that information to manually route the requests to different response generators.

giveRandomUUID is a response generator function that sets a random UUID string to response. Go's crypto package has a Read function that fills random characters into a byte array.

  1. Now add a main function to the module using the ServeMux object. We should pass our ServeMux to the http.ListenAndServe function to get our content served. We are serving our content on port 8000:
package main

import (
"net/http"
)

func main() {
mux := &UUID{}
http.ListenAndServe(":8000", mux)
}

We use UUID as a multiplexer in the ListenAndServe function, which starts an HTTP server. The server executes the ServeHTTP method that is defined preceding on the mux object.

  1. Run the following command from your shell/Terminal:
go run $GOPATH/src/github.com/git-user/chapter2/uuidGenerator/main.go
  1. We can make a curl request like this to make a request to the web server that is listening on port 8000:
curl -X GET http://localhost:8000/

The response that is returned will be a random string:

544f5519592ac25bb2c0
Use Ctrl + C or Cmd + C to stop your Go server. If you are running it as a background process, use sudo kill `sudo lsof -t -i:8000` to kill a process running on port 8000.

Until now, we have worked with a single handler. Let us see how we can add multiple handlers to route to different function handlers using ServeMux.

Adding multiple handlers using ServeMux

Let us say we have an API requirement that generates random numbers of different types such as int, float, and so on. The custom multiplexer (mux) we developed can be cumbersome when there are multiple endpoints with different functionalities. To add that logic, we need to add multiple if/else conditions to manually check the URL route. To overcome that complex code structure, we can instantiate a new in-built ServeMux object and define many handlers. Let's look at the code with ServeMux:

newMux := http.NewServeMux()

newMux.HandleFunc("/randomFloat", func(w http.ResponseWriter,
r *http.Request) {
fmt.Fprintln(w, rand.Float64())
})

newMux.HandleFunc("/randomInt", func(w http.ResponseWriter,
r *http.Request) {
fmt.Fprintln(w, rand.Int(100))
})

This code snippet shows how to create a ServeMux and attach multiple handlers to it.

randomFloat and randomInt are the two routes we create for returning a random float and random int, respectively. Now, we pass that to the ListenAndServe function. Int(100) returns a random integer number from the range 0-100.

For more details on random functions, visit the Go random package page at: http://golang.org.

Let us see a complete example:

  1. Create a file to hold our program and call it multipleHandlers.go in the following path:
touch -p $GOPATH/src/github.com/git-user/chapter2/multipleHandlers/main.go
  1. Now create a main function and add the code for creating the ServeMux object and function handlers.
  2. Finally, run the server with the http.ListenAndServe method:
package main

import (
"fmt"
"math/rand"
"net/http"
)

func main() {
newMux := http.NewServeMux()
newMux.HandleFunc("/randomFloat", func(w http.ResponseWriter,
r *http.Request) {
fmt.Fprintln(w, rand.Float64())
})
newMux.HandleFunc("/randomInt", func(w http.ResponseWriter,
r *http.Request) {
fmt.Fprintln(w, rand.Intn(100))
})
http.ListenAndServe(":8000", newMux)
}
  1. We can run the program directly using the run command:
go run $GOPATH/src/github.com/git-user/chapter2/multipleHandlers/main.go
  1. Now, let us fire two curl commands and see the output:
curl -X GET http://localhost:8000/randomFloat
curl -X GET http://localhost:8000/randomInt

The responses will be:

0.6046602879796196
87

We saw how we can create a URL router with basic Go constructs. Let us have a look at a few popular URL routing frameworks that are widely used by the Go community for their API servers.

You have been reading a chapter from
Hands-On RESTful Web Services with Go - Second Edition
Published in: Feb 2020
Publisher: Packt
ISBN-13: 9781838643577
Register for a free Packt account to unlock a world of extra content!
A free Packt account unlocks extra newsletters, articles, discounted offers, and much more. Start advancing your knowledge today.
Unlock this book and the full library FREE for 7 days
Get unlimited access to 7000+ expert-authored eBooks and videos courses covering every tech area you can think of
Renews at $19.99/month. Cancel anytime