DEV Community

stungnet
stungnet

Posted on

Making a basic HTTP server with Golang

Image description

Golang is widely used for building web applications. The ease of spinning up a HTTP server is one of its key features and today I'm going to show you just how easy it is to spin one up in a few lines. Then register some paths that will show some strings let's get started!

Finished code:

package main

import (
    "fmt"      // formatting and printing values to the console.
    "log"      // logging messages to the console.
    "net/http" // Used for build HTTP servers and clients.
)

// Port we listen on.
const portNum string = ":8080"

// Handler functions.
func Home(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Homepage")
}

func Info(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Info page")
}

func main() {
    log.Println("Starting our simple http server.")

    // Registering our handler functions, and creating paths.
    http.HandleFunc("/", Home)
    http.HandleFunc("/info", Info)

    log.Println("Started on port", portNum)
    fmt.Println("To close connection CTRL+C :-)")

    // Spinning up the server.
    err := http.ListenAndServe(portNum, nil)
    if err != nil {
        log.Fatal(err)
    }
}
Enter fullscreen mode Exit fullscreen mode

Required packages

For this we could really use just two packages fmt and net/http known as (http), but I enjoy having log to print certain things out in my code. If you aren't familar with these packages I've commented there use case next to them.

import (
    "fmt"      // formatting and printing values to the console.
    "log"      // logging messages to the console.
    "net/http" // Used for build HTTP servers and clients.
)
Enter fullscreen mode Exit fullscreen mode

Defining handler functions

Handler functions by name will handle incoming HTTP requests. These functions will take two arguments http.ResponseWriter which we call w and r a pointer to a http.Request this is standard for declaring a handler function.

Anatomy of a handler function:

// handlerFunc handles incoming HTTP requests.
func handlerFunc(w http.ResponseWriter, r *http.Request) {
    // Message here to the response writer.
}
Enter fullscreen mode Exit fullscreen mode

So what are these two arguments? when we make a request to a HTTP server, the server must process this and send back a response back to the client. Our http.ResponseWriter is used to write this response back to the client, and the http.Request object contains information about the incoming request.

So filling in our handler functions with some data now we write strings that will appear on our pages saying Homepage and Info. This is where you would pass your HTML templates if we were creating a web app. For now we just want to see our strings appear on the page.

func Home(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Homepage")
}

func Info(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Info")
}
Enter fullscreen mode Exit fullscreen mode

Handling the func

Now to handle the functions we just created we use the http.HandleFunc function. this function will take two arguments, a path as a string and a handler function which we just created above.

The basic pattern of a HandleFunc is below:

// HandleFunc is used to register a handler function for a specific path on your HTTP server.
http.HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
Enter fullscreen mode Exit fullscreen mode

Now let's register some paths with the handler functions we created earlier.

// Keeping it simple we will place them in our main function.
func main(){

    http.HandleFunc("/", Home)
    http.HandleFunc("/info", Info)
    }
Enter fullscreen mode Exit fullscreen mode

We've now created two paths by registering our handler functions to /for our homepage and /info for our info page. Let's now learn how we can spin up our server on our chosen port.

Can you hear me?

The last part is spinning up our server and listening. Listening in terms of network programming refers to the process of waiting for incoming network connections. Using the http.ListenAndServe function we can start a HTTP server and "listen" for incoming requests on a specified network address and port. Once a reuqest is received, it is passed to the appropriate handler function for processing.

Anatomy of a ListenAndServe:

http.ListenAndServe(port, ServeMux)
Enter fullscreen mode Exit fullscreen mode

Now let's listen on port 8080 and for our ServeMux we are just using the default http.ServeMux() by using nil. ListenAndServe also returns a err, so we can error check.

// Spinning up the server.
err := http.ListenAndServe(portNum, nil)
if err != nil {
    log.Fatal(err)
}
Enter fullscreen mode Exit fullscreen mode

Now run your main.go with go run main.go and visit your_ip_here:8080 or your_ip_here:8080/info in your browser to see a string printed on your new HTTP server and registered paths.

Image description

Congratulations on starting up a HTTP server, in the next post I'll show you how to add some HTML to this!

Top comments (0)