Go for the web

Golang is a high-performance programming language. It has fantastic features, but the web part might be mysterious when you are a beginner.

Installation

You need to install Golang on your machine before reading this tutorial.

Getting started

Golang comes quite close to C, but it’s IMHO easier to extend built-in features and other things in Go. You can use Go for an extensive range of projects.

Server/client

Golang is excellent for web applications too. Think about it. What do you need to run web applications?

You would need a client and a server. The browser would be an excellent client.

You enter some URL in the browser, which sends a request to the server. The server processes the request and returns the results. The browser displays the results.

HTTP package

Go has an HTTP package for that.

To see it in action, create a new file in your Go path and paste the following inside, for example, Main.go :

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func (w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hi, folks!")
    })
    http.ListenAndServe(":777", nil)
}

Then open your terminal and type :

go run Main.go

Then go to http://localhost:777.

HandleFunc() allows for mapping URLs and ListenAndServe() starts an HTTP server.

A function needs both ResponseWriter, http.Request to be a HandleFunc. The first one allows for displaying stuff with the browser (“writer”). The second one allows for grabbing the request, which is particularly useful to handle forms.

We use the fmt package to handle formatted I/O.

Improving code

The code above is palatable, but it does not handle errors, and it would be nice to split code :

package main

import (
    "fmt"
    "log"
    "net/http"
)

func sayHello(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Hi, folks!")
}

func main() {
    http.HandleFunc("/", sayHello)
 
    if err := http.ListenAndServe(":777", nil); err != nil {
    	log.Fatal(err)
    }
}

Here we still have our HandleFunc, but it’s a little more readable, and we log errors with the log package.

Goroutines and concurrency

A goroutine is a lightweight thread managed by the Go runtime.

Source

For each HTTP request, Go executes what we call a goroutine, and this is why it’s dope for performance! Go automatically uses concurrency.

Grab requests

Thanks to our HandleFunc, we can easily extract parameters and other information.

GET parameters

Let’s say you want to implement a search feature in your web application. You could start with this :

package main

import (
    "fmt"
    "log"
    "net/http"
)

func search(w http.ResponseWriter, r *http.Request) {
	s := r.URL.Query().Get("s")
    fmt.Fprintf(w, "You have searched '%v'.", s)
}

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

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

Open the terminal, run go run Main.go, and go to http://localhost:777/?s=chocolate

You will see :

You have searched ‘chocolate.’

You would add some HTML here with a search input. We will see how to include HTML templates in the next section.

POST requests and templates

It’s possible to create templates to add your HTML. For example, signin.html.

We need to display that form on our page. To achieve that, I recommend the template package :

{{define "signin"}}
<!DOCTYPE html>
<html lang="en">
    <head>
        <meta charset="utf-8">
        <title>Sign in</title>
    </head>
    <body>
    	<form action="/signin" method="post">

		  <label for="email">Your email:</label>
		  <input type="email" id="email" name="email" required> <br />

		  <label for="passwd">Your password:</label>
		  <input type="passwd" id="passwd" name="passwd" required><br />

		  <input type="submit" value="Sign in">

		</form>
	</body>
</html>
{{end}}

And in our go script, something like :

package main

import (
    "log"
    "html/template"
    "net/http"
)

func signin(w http.ResponseWriter, r *http.Request) {
	
    t := template.New("Sign in")
    t = template.Must(t.ParseFiles("signin.html"))
    err := t.ExecuteTemplate(w, "signin", r)

    if err != nil {
        log.Fatalf("Template execution: %s", err)
    }
}

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

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

However, we also want the submitted data from our users. We can use our custom signin function to process form when the HTTP method is POST:

package main

import (
    "log"
    "fmt"
    "html/template"
    "net/http"
)

func signin(w http.ResponseWriter, r *http.Request) {

    t := template.New("Sign in")
    t = template.Must(t.ParseFiles("signin.html"))
    err := t.ExecuteTemplate(w, "form", r)

    if err != nil {
        log.Fatalf("Template execution: %s", err)
    }

    if r.Method == "POST" {
        if err := r.ParseForm(); err != nil {
            log.Fatal(err)
        }
        fmt.Fprintf(w, "email is %v and password is %v", r.Form["email"], r.Form["passwd"])
    }

}

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

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

Run go run Main.go and go back to your form http://localhost:777/signin to submit. You will get both email and password displayed, for example :

email is [mynameisK@hotmail.com] and password is [cheater!alpha]

Security disclaimer

I like the template package because it has extra-cool features, and it takes care of some critical security points. You can even pass data back and forth, give it a try, it’s an excellent package.

Indeed here it’s just an example to demonstrate how to quickly render web stuff in Golang. You mustn’t process a password like that in real life. Likewise, you should escape any data before using it, never trust user inputs, especially when creating a search feature.

Wrap up

I hope you liked this short introduction to Golang and the web. Golang is quite more straightforward and more accessible than C. Its syntax is short and concise.

Its HTTP package is powerful and efficient. You can use it in production.