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
Routing
- URL pattern matching
- Route parameters
- Middleware support
- Static file serving
Middleware
- Request logging
- Authentication
- CORS handling
- Response compression
Sessions
- Session management
- Cookie handling
- State persistence
- Security considerations
Authentication
- User authentication
- JWT implementation
- OAuth integration
- Role-based access control
REST APIs
- RESTful principles
- JSON handling
- API versioning
- Documentation
GraphQL
- Schema definition
- Resolvers
- Mutations
- Subscriptions
WebSockets
- Real-time communication
- Connection handling
- Message broadcasting
- Error handling
Popular Web Frameworks
Standard Library
http.HandleFunc("/", handler) http.ListenAndServe(":8080", nil)
Gin
r := gin.Default() r.GET("/ping", func(c *gin.Context) { c.JSON(200, gin.H{ "message": "pong", }) }) r.Run()
Echo
e := echo.New() e.GET("/", func(c echo.Context) error { return c.String(http.StatusOK, "Hello, World!") }) e.Start(":8080")
Best Practices
Project Structure
├── cmd/ │ └── server/ │ └── main.go ├── internal/ │ ├── handlers/ │ ├── middleware/ │ └── models/ ├── pkg/ │ └── database/ └── web/ ├── templates/ └── static/
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) } }
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
Input Validation
func validateInput(input string) error { if len(input) > 100 { return errors.New("input too long") } // Additional validation return nil }
HTTPS
func main() { // Redirect HTTP to HTTPS go http.ListenAndServe(":80", http.HandlerFunc(redirect)) // HTTPS server http.ListenAndServeTLS(":443", "cert.pem", "key.pem", nil) }
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
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)
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
- Learn about Web Servers
- Explore Routing
- Study Middleware
- Understand Sessions
- Master Authentication
- Build REST APIs
- Implement GraphQL
- Work with WebSockets