Web Development

Medium45 min read

Web Development Fundamentals

Why net/http Matters

The Problem: Rolling your own HTTP server in Go is tempting but you'll re-invent middleware, routing, and validation badly.

The Solution: net/http is solid by itself; chi or echo add ergonomic routing without dragging in heavy frameworks; encoding/json handles serialization out of the box.

Real Impact: Go is the standard for high-throughput APIs because the language, runtime, and HTTP stack are designed together for performance.

Real-World Analogy

Think of net/http as a hotel front desk:

  • Handler = a clerk who serves one type of request
  • Router = the lobby concierge directing guests to the right clerk
  • Middleware = the security check every guest passes through first
  • Context = the guest's keycard — used by every clerk they meet
  • ResponseWriter = the printer that produces the reply on the way out

Go Web Development Ecosystem

Go provides excellent built-in support for web development with the net/http package, along with a rich ecosystem of frameworks and libraries for building scalable web applications and APIs.

Go Web Development Stack HTTP Foundation (net/http) Request/Response Routing Handlers Middleware Static Files Web Frameworks • Gin (Fast) • Echo (Feature-rich) • Fiber (Express-like) Middleware • Authentication • Logging & Metrics • CORS & Security API Tools • REST APIs • GraphQL • gRPC HTTP Request Flow Client Request Router Middleware Handler Response Common Patterns MVC Pattern Models • Views Controllers API First JSON APIs RESTful Design Microservices Service Mesh Distributed Systems Full Stack Templates Server-side Rendering

HTTP Foundation

Go's net/http package provides a robust foundation for web applications with built-in support for HTTP/2, TLS, and efficient request handling.

Built-in HTTP/2

Framework Ecosystem

Rich ecosystem of web frameworks offering different trade-offs between performance, features, and ease of use for various application needs.

Gin Echo Fiber

Performance & Scalability

Go's concurrency model and efficient runtime make it ideal for building high-performance web services that can handle thousands of concurrent requests.

Concurrent Scalable

Basic HTTP Server

Create a web server using Go's net/http package.

package main

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

func main() {
    // Handle routes
    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/about", aboutHandler)
    http.HandleFunc("/api/users", usersAPIHandler)
    
    // Serve static files
    fs := http.FileServer(http.Dir("./static"))
    http.Handle("/static/", http.StripPrefix("/static/", fs))
    
    log.Println("Server starting on :8080")
    if err := http.ListenAndServe(":8080", nil); err != nil {
        log.Fatal(err)
    }
}

func homeHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Content-Type", "text/html")
    fmt.Fprintf(w, "

Welcome to Go Web Server

") } func aboutHandler(w http.ResponseWriter, r *http.Request) { data := struct { Title string Message string }{ Title: "About Us", Message: "Built with Go", } tmpl := template.Must(template.New("about").Parse(`

{{.Title}}

{{.Message}}

`)) tmpl.Execute(w, data) } func usersAPIHandler(w http.ResponseWriter, r *http.Request) { w.Header().Set("Content-Type", "application/json") switch r.Method { case http.MethodGet: fmt.Fprint(w, `{"users": [{"id": 1, "name": "John"}]}`) case http.MethodPost: // Handle POST request default: http.Error(w, "Method not allowed", http.StatusMethodNotAllowed) } }

Gin Web Framework

Build robust web applications using the Gin framework.

package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)

type Todo struct {
    ID        string `json:"id"`
    Title     string `json:"title" binding:"required"`
    Completed bool   `json:"completed"`
}

var todos = []Todo{
    {ID: "1", Title: "Learn Go", Completed: false},
    {ID: "2", Title: "Build API", Completed: false},
}

func main() {
    router := gin.Default()
    
    // Middleware
    router.Use(gin.Logger())
    router.Use(gin.Recovery())
    
    // Static files
    router.Static("/assets", "./assets")
    router.LoadHTMLGlob("templates/*")
    
    // HTML rendering
    router.GET("/", func(c *gin.Context) {
        c.HTML(http.StatusOK, "index.html", gin.H{
            "title": "Home Page",
            "todos": todos,
        })
    })
    
    // API routes
    api := router.Group("/api")
    {
        api.GET("/todos", getTodos)
        api.GET("/todos/:id", getTodoByID)
        api.POST("/todos", createTodo)
        api.PUT("/todos/:id", updateTodo)
        api.DELETE("/todos/:id", deleteTodo)
    }
    
    router.Run(":8080")
}

func getTodos(c *gin.Context) {
    c.JSON(http.StatusOK, todos)
}

func getTodoByID(c *gin.Context) {
    id := c.Param("id")
    
    for _, todo := range todos {
        if todo.ID == id {
            c.JSON(http.StatusOK, todo)
            return
        }
    }
    
    c.JSON(http.StatusNotFound, gin.H{"error": "Todo not found"})
}

func createTodo(c *gin.Context) {
    var newTodo Todo
    
    if err := c.ShouldBindJSON(&newTodo); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }
    
    todos = append(todos, newTodo)
    c.JSON(http.StatusCreated, newTodo)
}

Template Rendering

Render dynamic HTML templates with Go's template engine.

// templates/layout.html
{{define "layout"}}



    {{.Title}}
    


        
    
{{template "content" .}}