Master HTTP programming in Go with interactive learning and quizzes
The net/http
package is Go’s standard library for building HTTP servers and clients. It is powerful, easy to use, and production-ready.
The net/http
package provides HTTP client and server implementations. It's part of the standard library and makes it simple to:
import "net/http"
ServeHTTP(http.ResponseWriter, *http.Request)
. Any struct or function that implements this can handle HTTP requests.package main import ("fmt"; "net/http") func handler(w http.ResponseWriter, r *http.Request) { fmt.Fprintf(w, "Hello, World!") } func main() { http.HandleFunc("/", handler); http.ListenAndServe(":8080", nil) }
HandleFunc: Registers a function to a route.
ListenAndServe: Starts the server and listens on port 8080.
Use this if you want custom types to handle HTTP requests.
type MyHandler struct{} func (m MyHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Handled by MyHandler")) } func main() { http.ListenAndServe(":8080", MyHandler{}) }
ServeMux
lets you register multiple routes.
func main() { mux := http.NewServeMux() mux.HandleFunc("/hello", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Hello route!")) }) mux.HandleFunc("/bye", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Goodbye!")) }) http.ListenAndServe(":8080", mux) }
Access URL query parameters easily:
func handler(w http.ResponseWriter, r *http.Request) { name := r.URL.Query().Get("name") fmt.Fprintf(w, "Hello, %s!", name) }
Call with /hello?name=John
func handler(w http.ResponseWriter, r *http.Request) { if r.Method == http.MethodPost { fmt.Fprintln(w, "POST received") } header := r.Header.Get("User-Agent") fmt.Fprintln(w, "User-Agent:", header) }
func main() { fs := http.FileServer(http.Dir("./static")) http.Handle("/static/", http.StripPrefix("/static/", fs)) http.ListenAndServe(":8080", nil) }
Place files in the ./static/
directory. Access them at /static/file.txt
A middleware wraps an http.Handler
to add extra logic.
func loggingMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { fmt.Println("Request URI:", r.RequestURI) next.ServeHTTP(w, r) }) } func main() { mux := http.NewServeMux() mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { w.Write([]byte("Welcome!")) }) loggedMux := loggingMiddleware(mux) http.ListenAndServe(":8080", loggedMux) }
Shutdown the server cleanly on Ctrl+C:
func gracefulShutdown(server *http.Server, quit <-chan os.Signal, done chan<- bool) { <-quit ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second) defer cancel() server.Shutdown(ctx) done <- true }
func jsonHandler(w http.ResponseWriter, r *http.Request) { response := map[string]string{"message": "Hello JSON"} w.Header().Set("Content-Type", "application/json") json.NewEncoder(w).Encode(response) }