Go Web Development

Go provides a powerful yet minimalistic standard library for building web applications.

Setting Up a Basic Web Server

Create a new directory for your project and initialize a Go module:

mkdir go-web-app && cd go-web-app
go mod init go-web-app

Now, create a main.go file with the following code:

package main

import (
    "fmt"
    "net/http"
)

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

func main() {
    http.HandleFunc("/", handler)
    fmt.Println("Server running on http://localhost:8080")
    http.ListenAndServe(":8080", nil)
}

Run the server:

go run main.go

Visit http://localhost:8080 in your browser, and you should see Hello, World!.

Routing with http.ServeMux

For better request handling, use http.ServeMux:

func main() {
    mux := http.NewServeMux()
    mux.HandleFunc("/", handler)
    mux.HandleFunc("/about", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "About Page")
    })

    fmt.Println("Server running on http://localhost:8080")
    http.ListenAndServe(":8080", mux)
}

Handling Query Parameters

You can extract query parameters from the request:

func queryHandler(w http.ResponseWriter, r *http.Request) {
    name := r.URL.Query().Get("name")
    if name == "" {
        name = "Guest"
    }
    fmt.Fprintf(w, "Hello, %s!", name)
}

Try accessing: http://localhost:8080/?name=Kostas.

Serving Static Files

To serve static assets like HTML, CSS, or images:

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

Place your files in a static/ folder and access them via http://localhost:8080/static/filename.

JSON API with encoding/json

To return JSON responses:

import (
    "encoding/json"
)

type Response struct {
    Message string `json:"message"`
}

func jsonHandler(w http.ResponseWriter, r *http.Request) {
    response := Response{Message: "Hello, JSON!"}
    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(response)
}

Graceful Shutdown with context

Handle server shutdown properly:

import (
    "context"
    "os"
    "os/signal"
    "time"
)

func main() {
    srv := &http.Server{Addr: ":8080", Handler: mux}
    go func() {
        if err := srv.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            fmt.Println("Server error:", err)
        }
    }()

    quit := make(chan os.Signal, 1)
    signal.Notify(quit, os.Interrupt)
    <-quit

    fmt.Println("Shutting down server...")
    ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
    defer cancel()
    srv.Shutdown(ctx)
}