1. go
  2. /web

Web Development in Go: A Complete Guide

Go is an excellent choice for web development, offering high performance, built-in concurrency, and a rich standard library. This guide covers everything you need to know about web development in Go.

Web Development Fundamentals

HTTP Server Basics

The net/http package provides everything needed to build web servers:

package main

import (
    "fmt"
    "net/http"
)

func main() {
    http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
        fmt.Fprintf(w, "Hello, World!")
    })
    
    fmt.Println("Server starting on :8080")
    http.ListenAndServe(":8080", nil)
}

Request Handling

Go's HTTP handler interface:

type Handler interface {
    ServeHTTP(ResponseWriter, *Request)
}

Example handler implementation:

type userHandler struct {
    db *sql.DB
}

func (h *userHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
    switch r.Method {
    case http.MethodGet:
        h.list(w, r)
    case http.MethodPost:
        h.create(w, r)
    default:
        http.Error(w, "Method not allowed", http.StatusMethodNotAllowed)
    }
}

Key Concepts

  1. Routing

    • URL pattern matching
    • Route parameters
    • Middleware support
    • Static file serving
  2. Middleware

    • Request logging
    • Authentication
    • CORS handling
    • Response compression
  3. Sessions

    • Session management
    • Cookie handling
    • State persistence
    • Security considerations
  4. Authentication

    • User authentication
    • JWT implementation
    • OAuth integration
    • Role-based access control
  5. REST APIs

    • RESTful principles
    • JSON handling
    • API versioning
    • Documentation
  6. GraphQL

    • Schema definition
    • Resolvers
    • Mutations
    • Subscriptions
  7. WebSockets

    • Real-time communication
    • Connection handling
    • Message broadcasting
    • Error handling
  1. Standard Library

    http.HandleFunc("/", handler)
    http.ListenAndServe(":8080", nil)
    
  2. Gin

    r := gin.Default()
    r.GET("/ping", func(c *gin.Context) {
        c.JSON(200, gin.H{
            "message": "pong",
        })
    })
    r.Run()
    
  3. Echo

    e := echo.New()
    e.GET("/", func(c echo.Context) error {
        return c.String(http.StatusOK, "Hello, World!")
    })
    e.Start(":8080")
    

Best Practices

  1. Project Structure

    ├── cmd/
    │   └── server/
    │       └── main.go
    ├── internal/
    │   ├── handlers/
    │   ├── middleware/
    │   └── models/
    ├── pkg/
    │   └── database/
    └── web/
        ├── templates/
        └── static/
    
  2. Error Handling

    func handleError(w http.ResponseWriter, err error) {
        switch e := err.(type) {
        case *CustomError:
            http.Error(w, e.Message, e.Code)
        default:
            http.Error(w, "Internal server error", http.StatusInternalServerError)
        }
    }
    
  3. Middleware Chain

    func chainMiddleware(h http.Handler, middleware ...func(http.Handler) http.Handler) http.Handler {
        for _, m := range middleware {
            h = m(h)
        }
        return h
    }
    

Security Considerations

  1. Input Validation

    func validateInput(input string) error {
        if len(input) > 100 {
            return errors.New("input too long")
        }
        // Additional validation
        return nil
    }
    
  2. HTTPS

    func main() {
        // Redirect HTTP to HTTPS
        go http.ListenAndServe(":80", http.HandlerFunc(redirect))
        
        // HTTPS server
        http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil)
    }
    
  3. CORS

    func corsMiddleware(next http.Handler) http.Handler {
        return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
            w.Header().Set("Access-Control-Allow-Origin", "*")
            next.ServeHTTP(w, r)
        })
    }
    

Performance Optimization

  1. Connection Pooling

    db, err := sql.Open("postgres", dsn)
    if err != nil {
        log.Fatal(err)
    }
    db.SetMaxOpenConns(25)
    db.SetMaxIdleConns(25)
    db.SetConnMaxLifetime(5 * time.Minute)
    
  2. Caching

    var (
        cache    = make(map[string][]byte)
        cacheMux sync.RWMutex
    )
    
    func getCached(key string) ([]byte, bool) {
        cacheMux.RLock()
        defer cacheMux.RUnlock()
        data, ok := cache[key]
        return data, ok
    }
    

Next Steps