Go Routing 101: Handling and Grouping Routes with net/http

Go 1.22 brings two enhancements to the net/http package’s router: method matching and wildcards. These features let you express common routes as patterns instead of Go code. Although they are simple to explain and use, it was a challenge to come up wi…


This content originally appeared on DEV Community and was authored by Kengo Wada

Go 1.22 brings two enhancements to the net/http package’s router: method matching and wildcards. These features let you express common routes as patterns instead of Go code. Although they are simple to explain and use, it was a challenge to come up with the right rules for selecting the winning pattern when several match a request.

Go 1.22 added new features to their net/http package to make it a good alternative to using third-party libraries. In this article, we will look at how to handle routing using Golang's net/http package. We will start with the basic route handling and then move on to grouping those routes.

Notes

  • This assumes you're using Go version >= 1.22
  • The repo for more details

Basic Routing

Let us start by looking at how to register your routes.

// main.go
package main

import (
    "log"
    "net/http"
)

func main() {
    router := http.NewServeMux()

    router.HandleFunc("GET /users/", getUsers)
    router.HandleFunc("POST /users/", createUser)
    router.HandleFunc("GET /users/{id}/", getUser)
    router.HandleFunc("DELETE /users/{id}/", deleteUser)

    err := http.ListenAndServe(":8000", router)
    if err != nil {
        log.Fatal(err)
    }
}

// Here goes the implementation for getUsers, getUser, createUser, deleteUser
// Check the repo in services/users/routes.go

type User struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Email string `json:"email"`
}

var users []User = []User{
    {ID: 1, Name: "Bumblebee", Email: "bumblebee@autobots.com"},
    {ID: 2, Name: "Optimus Prime", Email: "optimus.prime@autobots.com"},
    {ID: 3, Name: "Ironhide", Email: "ironhide@autobots.com"},
    {ID: 4, Name: "Hot Rod", Email: "hot.rod@autobots.com"},
}

func getUsers(w http.ResponseWriter, r *http.Request) {
    response := map[string]any{
        "message": "Done",
        "users":   users,
    }
    utils.WriteJSONResponse(w, http.StatusOK, response)
}

Let's go through the above code:

  1. router := http.NewServeMux() This creates a new request multiplexer. When a request is made, the router examines the request’s URL and selects the most appropriate handler to serve the request.
  2. router.HandleFunc("GET /users/", getUsers) This registers the /users/ route and indicates that this will be a GET method route.
  3. utils.WriteJSONResponse This is a utility function to create a JSON response and can be found in the repo in utils/utils.go

Note: When making requests make sure to add the trailing slash. Doing otherwise will return a 404 not found response
Example:

  • http://localhost:8000/users returns 404
  • http://localhost:8000/users/ returns the correct server response

Sample Request:

  • Request: GET http://localhost:8000/users/
  • Response:
// statusCode: 200
{
    "message": "Done",
    "users": [
        {
            "id": 1,
            "name": "Bumblebee",
            "email": "bumblebee@autobots.com"
        },
        {
            "id": 2,
            "name": "Optimus Prime",
            "email": "optimus.prime@autobots.com"
        },
        {
            "id": 3,
            "name": "Ironhide",
            "email": "ironhide@autobots.com"
        },
        {
            "id": 4,
            "name": "Hot Rod",
            "email": "hot.rod@autobots.com"
        }
    ]
}

Grouping Routes

As we can see from the above, this would require us to register all endpoints in the same place and can get out of hand quickly. Grouping routes helps you keep your code organized, scalable, and maintainable by putting related routes and logic together. It allows you to apply middleware selectively, encourages reusability, and improves readability, especially as your application grows.
Now let us look at how we can group routes

We will start by registering routes locally in the package where their handler functions are defined. The next step is to bring all those various routes together and start the server.

// services/users/routes.go
package user

import (
    "fmt"
    "net/http"
    "strconv"

    "<your-project-name>/gorouting/utils"
)

type Handler struct{}

func NewHandler() *Handler {
    return &Handler{}
}

func (h *Handler) RegisterRoutes() *http.ServeMux {
    r := http.NewServeMux()
    r.HandleFunc("GET /", getUsers)
    r.HandleFunc("POST /", createUser)

    r.HandleFunc("GET /{id}/", getUser)
    r.HandleFunc("DELETE /{id}/", deleteUser)

    return r
}
// ...

Let's go through the code.

  1. func NewHandler() *Handler This creates a new Handler that is used for dependency injection such as adding access to a database should one be present.
  2. func (h *Handler) RegisterRoutes() *http.ServeMux Here we create a new ServeMux and register routes.
// cmd/api/api.go
package api

import (
    "log"
    "net/http"

    "<your-project-name>/services/user"
)

type APIServer struct {
    addr string
}

func NewAPIServer(addr string) *APIServer {
    return &APIServer{addr: addr}
}

func (s *APIServer) Run() error {
    userHandler := user.NewHandler()
    userRouter := userHandler.RegisterRoutes()

    router := http.NewServeMux()
    router.Handle("/users/", http.StripPrefix("/users", userRouter))

    log.Println("Starting server on port", s.addr)
    return http.ListenAndServe(s.addr, router)
}

Here we are going to focus on the Run method.

  1. userHandler := user.NewHandler() This creates a new handler and this is the point where things like database connections can be passed along to the endpoints that need them. This is called dependency injection.
  2. userRouter := userHandler.RegisterRoutes() This creates a ServeMux containing the user routes.
  3. router.Handle("/api/v1/users/", http.StripPrefix("/api/v1/users", userRouter)) This registers the users with the base URL of /users/. StripPrefix removes the specified prefix from the request URL before routing it to userRouter.
// cmd/main.go
package main

import (
    "log"

    "<your-project-name>/cmd/api"
)

func main() {
    server := api.NewAPIServer(":8000")
    if err := server.Run(); err != nil {
        log.Fatal(err)
    }
}

“With Go 1.22, net/http is now more versatile, offering route patterns that improve clarity and efficiency. This approach to grouping routes shows how easy it is to maintain scalable code while taking advantage of Go’s built-in routing capabilities.” ChatGPT

Now that we have managed to group the user routes. Clone the repo and try adding another service.


This content originally appeared on DEV Community and was authored by Kengo Wada


Print Share Comment Cite Upload Translate Updates
APA

Kengo Wada | Sciencx (2024-11-02T13:17:43+00:00) Go Routing 101: Handling and Grouping Routes with net/http. Retrieved from https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/

MLA
" » Go Routing 101: Handling and Grouping Routes with net/http." Kengo Wada | Sciencx - Saturday November 2, 2024, https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/
HARVARD
Kengo Wada | Sciencx Saturday November 2, 2024 » Go Routing 101: Handling and Grouping Routes with net/http., viewed ,<https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/>
VANCOUVER
Kengo Wada | Sciencx - » Go Routing 101: Handling and Grouping Routes with net/http. [Internet]. [Accessed ]. Available from: https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/
CHICAGO
" » Go Routing 101: Handling and Grouping Routes with net/http." Kengo Wada | Sciencx - Accessed . https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/
IEEE
" » Go Routing 101: Handling and Grouping Routes with net/http." Kengo Wada | Sciencx [Online]. Available: https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/. [Accessed: ]
rf:citation
» Go Routing 101: Handling and Grouping Routes with net/http | Kengo Wada | Sciencx | https://www.scien.cx/2024/11/02/go-routing-101-handling-and-grouping-routes-with-net-http/ |

Please log in to upload a file.




There are no updates yet.
Click the Upload button above to add an update.

You must be logged in to translate posts. Please log in or register.