In a typical web application, there are bound to be multiple routes that you want to expose to the users. In this post, I will explain how you can handle routing in a Go web server.

Also, I will show how you can handle URL parameters in a Go web server so that you can accept relevant input from the user wherever applicable.

In case you are completely new to building a web application using Go, I suggest you to go through my earlier post on creating a Go HTTP Web Server.

1 – Understand Web Server Routing in Go

Routing is a fundamental aspect of web applications.

It basically determines how incoming HTTP requests are sent to specific handlers or functions. These specific handlers allow us to perform dynamic content delivery.

In Go, routing is seamlessly handled through the net/http package. This package provides developers with the tools to define routes, specify how to match them and designate appropriate handler functions.

Here’s an example:

http.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) {
   fmt.Fprintln(w, "Hello, World!")
})

As you can see the http.HandleFunc method allows you to map URL patterns to specific functions.

In this example, any incoming request to the “/hello” URL pattern triggers the function that responds with “Hello, World!“.

2 – Handling HTTP Request Methods in Go

The next logical step is to see how you can handle specific HTTP Request Methods in your Go Web Servers.

For beginners, HTTP request methods such as GET, POST, PUT and DELETE play a pivotal role in web development. They allow clients to communicate their intentions to the web servers in a much more effective manner.

Let’s look at the an example of a basic handler for GET method.

http.HandleFunc("/test", func(w http.ResponseWriter, r *http.Request) {
   if r.Method == http.MethodGet {
      fmt.Fprintf(w, "Testing a GET request!")
    } else {
      http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
})

In this snippet, we define a route for “/test”.

Then, we check whether the incoming request is a GET method. If that’s the case, we respond with a friendly greeting message. Otherwise, we return a “Method not allowed” response.

Here are examples to handle other methods such as POST and PUT.

// Handling a POST request
http.HandleFunc("/create", func(w http.ResponseWriter, r *http.Request) {
     if r.Method == http.MethodPost {
	// Handle POST data and process it here
	fmt.Fprintln(w, "Data has been created!")
     } else {
	http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
     }
})

// Handling a PUT request
http.HandleFunc("/update", func(w http.ResponseWriter, r *http.Request) {
     if r.Method == http.MethodPut {
	// Handle PUT data and update resources here
	fmt.Fprintln(w, "Data has been updated!")
	} else {
	http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
     }
})

As you may have noticed, handling HTTP methods like POST or PUT follow a similar pattern where you can utilize the r.Method attribute to differentiate between them.

3 – URL Parameters in Go HTTP Web Server

Moving on, the next logical item is to handle URL parameters.

Basically, URL parameters are essential to add dynamism to your web applications. They make your applications interactive by letting the users pass some input and receive output according to that.

URL parameters are integrated directly into the URL path. For example, in a URL like “/users/567”, “567” is a URL parameter that might represent a user’s unique identifier.

You can extract and use these URL parameters from the http.Request object.

See the below example:

http.HandleFunc("/products/", func(w http.ResponseWriter, r *http.Request){
   // Extract the "id" parameter from the URL
   id := strings.TrimPrefix(r.URL.Path, "/product/")

   // Use the extracted "id" in your logic (e.g., fetch user data)
   fmt.Fprintf(w, "Fetching user with ID: %s", id)
})

In this snippet, we define a route for “/products” and within the handling function, we extract the “id” parameter from the URL path using strings.TrimPrefix method.

Basically, we can use this “id” parameter to fetch the user’s data from a database or generate dynamic content for the user. In this demo, we simply return it as part of the response.

For more complex route matching, Go also allows the use of regular expressions to create complex route patterns.

See the below example:

// Define a route using a regular expression
regExp := regexp.MustCompile(`^/users/(\d+)$`)
http.HandleFunc("/users/", func(w http.ResponseWriter, r *http.Request) {
	match := regExp.FindStringSubmatch(r.URL.Path)
	if match != nil {
	   userID := match[1]
	   // Handle the product with the extracted ID
	   fmt.Fprintf(w, "User ID: %s", userID)
	} else {
	   http.Error(w, "Not Found", http.StatusNotFound)
	}
})

In this example, the regular expression ^/users/(\d+)$ matches URLs like “/users/123” and captures the user ID for further processing.

Conclusion

That’s all for this post.

In this post, you got a fair amount of idea on handling web server routing in Go. You also learnt how to handle URL parameters, different request methods like GET, POST and so on to create dynamic and interactive web applications.

In case you want to take things further, check out this post on how to enable logging in Go web server with Zap.

If you have any comments or queries about this post, please feel free to mention in the comments section below.

Categories: BlogGolang

Saurabh Dashora

Saurabh is a Software Architect with over 12 years of experience. He has worked on large-scale distributed systems across various domains and organizations. He is also a passionate Technical Writer and loves sharing knowledge in the community.

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *