You're reading a sample of this book. Grab the full version here.

2.3. Web Application Basics

Now that everything is set up correctly let's make the first iteration of our web application. We'll begin with the three absolute essentials:

Let's put these components together in the main.go file to make a working application.

File: main.go
package main

import (

// Define a home handler function which writes a byte slice containing
// "Hello from Snippetbox" as the response body.
func home(w http.ResponseWriter, r *http.Request) {
    w.Write([]byte("Hello from Snippetbox"))

func main() {
    // Use the http.NewServeMux() function to initialize a new servemux, then
    // register the home function as the handler for the "/" URL pattern.
    mux := http.NewServeMux()
    mux.HandleFunc("/", home)

    // Use the http.ListenAndServe() function to start a new web server. We pass in
    // two parameters: the TCP network address to listen on (in this case ":4000")
    // and the servemux we just created. If http.ListenAndServe() returns an error
    // we use the log.Fatal() function to log the error message and exit.
    log.Println("Starting server on :4000")
    err := http.ListenAndServe(":4000", mux)

Note: Our home handler function is just a regular Go function which takes two parameters: the http.ResponseWriter provides methods for assembling a HTTP response and sending it to the user, and http.Request is a struct which holds information about the current request (such as the HTTP method and the URL being requested). We'll talk more about these and demonstrate how to use these as we progress through the build.

When you run this code, it should start a web server listening on port 4000 of your local machine. Each time the server receives a new HTTP request it will pass the request on to the servemux and — in turn — the servemux will check the URL path and dispatch the request to the matching handler.

Let's give this a whirl. Save your main.go file and then try running it from your terminal using the go run command.

$ cd $HOME/code/snippetbox
$ go run main.go
2018/08/02 10:08:07 Starting server on :4000

While the server is running, open a web browser and try visiting http://localhost:4000/. If everything has gone to plan you should see a page which looks a bit like this:


Important note: Before we continue, I should explain that Go's servemux treats the URL pattern "/" like a catch-all. So at the moment all HTTP requests will be handled by the home function regardless of their URL path. For instance, you can visit a different URL path like http://localhost:4000/foo, and you'll receive exactly the same response. We'll talk more about this in the next chapter.

If you head back to your terminal window, you can stop the web server by pressing Ctrl+c on your keyboard.

Additional Information

Network Addresses

The TCP network address that you pass to http.ListenAndServe() should be in the format "host:port". If you omit the host (like we did with ":4000") then the server will listen on all your computer's available network interfaces. Generally, you only need to specify a host in the address if your computer has multiple network interfaces and you want to listen on just one of them.

In other Go projects or documentation you might sometimes see network addresses written using named ports like ":http" or ":http-alt" instead of a number. If you use a named port then Go will attempt to look up the relevant port number from your /etc/services file when starting the server, or will return an error if a match can't be found.


In the code above we're using Go's log.Println() and log.Fatal() functions to output log messages. Both these functions output messages via Go's 'standard' logger, which — by default — prefixes messages with the local date and time and writes them to the standard error stream (which should display in your terminal window).

The log.Fatal() function will also call os.Exit(1) after writing the message, causing the application to immediately exit.