Building a Web Server in Go using the net/http Package

Table of Contents

  1. Introduction
  2. Prerequisites
  3. Setup
  4. Creating a Simple HTTP Server
  5. Handling Requests
  6. Adding Routes
  7. Serving Static Files
  8. Conclusion

Introduction

Welcome to this tutorial on creating a web server in Go using the net/http package. In this tutorial, we will learn how to build a simple HTTP server, handle requests, add routes, and serve static files. By the end of this tutorial, you will have a basic understanding of how to create a web server in Go.

Prerequisites

Before starting this tutorial, you should have the following prerequisites:

  • Basic knowledge of the Go programming language
  • Go installed on your machine

Setup

To get started, let’s set up a new Go project. Create a new directory for your project and initialize a new Go module using the following commands:

$ mkdir web-server
$ cd web-server
$ go mod init example.com/web-server

Creating a Simple HTTP Server

Now that we have set up our project, let’s create a simple HTTP server. Create a new file called main.go and add the following code:

package main

import (
	"fmt"
	"net/http"
)

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

	http.ListenAndServe(":8080", nil)
}

In this code, we import the fmt package for formatting our response and the net/http package for handling HTTP requests. We define a handler function for the root path (“/”) that writes “Hello, World!” as the response. Lastly, we start the server on port 8080 using http.ListenAndServe().

To run the server, use the following command:

$ go run main.go

Now, if you open your browser and navigate to http://localhost:8080, you should see the “Hello, World!” message.

Handling Requests

In the previous example, we handled requests using the root path (“/”). Let’s now look at how to handle different types of requests.

package main

import (
	"fmt"
	"net/http"
)

func main() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		if r.Method == "GET" {
			fmt.Fprintf(w, "This is a GET request")
		} else if r.Method == "POST" {
			fmt.Fprintf(w, "This is a POST request")
		} else {
			fmt.Fprintf(w, "This is an unsupported request method")
		}
	})

	http.ListenAndServe(":8080", nil)
}

In this updated code, we use the r.Method field of the http.Request object to determine the type of request. If it’s a GET request, we respond accordingly. If it’s a POST request, we respond with a different message. For any other type of request, we display an “unsupported request method” message.

Adding Routes

Handling all requests in a single handler function can become impractical as your web application grows. Let’s see how we can add multiple routes to our server.

package main

import (
	"fmt"
	"net/http"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to the home page!")
}

func aboutHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "This is the about page.")
}

func contactHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Contact us at [email protected]")
}

func main() {
	http.HandleFunc("/", homeHandler)
	http.HandleFunc("/about", aboutHandler)
	http.HandleFunc("/contact", contactHandler)

	http.ListenAndServe(":8080", nil)
}

In this example, we define separate handler functions for each route (“/”, “/about”, and “/contact”). We then pass these functions as arguments to http.HandleFunc() to associate them with their respective routes.

Serving Static Files

In addition to handling requests and routing, you may often need to serve static files like CSS, JavaScript, or images. Let’s see how to serve static files using the net/http package.

First, create a new directory called static in your project’s root directory. Inside the static directory, create a file named styles.css with some CSS styles:

h1 {
    color: blue;
}

Now, let’s modify our server code to serve this static file:

package main

import (
	"fmt"
	"net/http"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprintf(w, "Welcome to the home page!")
}

func main() {
	http.HandleFunc("/", homeHandler)

	fs := http.FileServer(http.Dir("static"))
	http.Handle("/static/", http.StripPrefix("/static/", fs))

	http.ListenAndServe(":8080", nil)
}

In this updated code, we add a handler function for the root path (“/”) as before. We then create a http.FileServer that serves files from the static directory. The http.Handle() function associates the file server with the “/static/” URL prefix, and http.StripPrefix() is used to remove the “/static/” prefix from the requested URL.

Now, if you save the styles.css file in the static directory, you can access it in the browser by visiting http://localhost:8080/static/styles.css.

Conclusion

In this tutorial, we have learned how to build a basic web server in Go using the net/http package. We covered handling requests, adding routes, and serving static files. You should now have a good foundation for building more complex web applications in Go.

Remember to check the official Go documentation and explore other packages to enhance your web server with features like authentication, session management, and database connectivity. Happy coding!