Serie: Go
go
90 righe
· Aggiornato 2026-04-18
main.go
Go/part1-language/examples/13_practical/main.go
// A small HTTP server that demonstrates routing, JSON, slog, middleware
// and graceful shutdown using only the standard library.
package main
import (
"context"
"encoding/json"
"errors"
"flag"
"log/slog"
"net/http"
"os"
"os/signal"
"syscall"
"time"
)
type pingResp struct {
Status string `json:"status"`
}
type echoResp struct {
Echo string `json:"echo"`
}
func ping(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(pingResp{Status: "ok"})
}
func echo(w http.ResponseWriter, r *http.Request) {
msg := r.URL.Query().Get("msg")
if msg == "" {
http.Error(w, "missing 'msg' query parameter", http.StatusBadRequest)
return
}
w.Header().Set("Content-Type", "application/json")
_ = json.NewEncoder(w).Encode(echoResp{Echo: msg})
}
func loggingMiddleware(logger *slog.Logger) func(http.Handler) http.Handler {
return func(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
next.ServeHTTP(w, r)
logger.Info("request",
slog.String("method", r.Method),
slog.String("path", r.URL.Path),
slog.Duration("dur", time.Since(start)),
)
})
}
}
func main() {
addr := flag.String("addr", ":8080", "listen address")
flag.Parse()
logger := slog.New(slog.NewJSONHandler(os.Stdout, nil))
mux := http.NewServeMux()
mux.HandleFunc("GET /ping", ping)
mux.HandleFunc("GET /echo", echo)
srv := &http.Server{
Addr: *addr,
Handler: loggingMiddleware(logger)(mux),
ReadHeaderTimeout: 5 * time.Second,
}
go func() {
logger.Info("server starting", slog.String("addr", *addr))
if err := srv.ListenAndServe(); err != nil && !errors.Is(err, http.ErrServerClosed) {
logger.Error("server failed", slog.Any("err", err))
os.Exit(1)
}
}()
stop := make(chan os.Signal, 1)
signal.Notify(stop, syscall.SIGINT, syscall.SIGTERM)
<-stop
logger.Info("shutdown signal received")
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
if err := srv.Shutdown(ctx); err != nil {
logger.Error("graceful shutdown failed", slog.Any("err", err))
}
logger.Info("bye")
}
Articoli correlati
Go
go
Aggiornato 2026-04-18
main.go
main.go — go source code from the Go learning materials (Go/Baasid/cmd/hashpw/main.go).
Leggi l'articolo →
Go
go
Aggiornato 2026-04-18
main.go
main.go — go source code from the Go learning materials (Go/Baasid/cmd/server/main.go).
Leggi l'articolo →
Go
go
Aggiornato 2026-04-18
docs.go
docs.go — go source code from the Go learning materials (Go/Baasid/docs/docs.go).
Leggi l'articolo →
Go
go
Aggiornato 2026-04-18
jwt.go
jwt.go — go source code from the Go learning materials (Go/Baasid/internal/auth/jwt.go).
Leggi l'articolo →
Go
go
Aggiornato 2026-04-18
password.go
password.go — go source code from the Go learning materials (Go/Baasid/internal/auth/password.go).
Leggi l'articolo →
Go
go
Aggiornato 2026-04-18
password_test.go
password_test.go — go source code from the Go learning materials (Go/Baasid/internal/auth/password_test.go).
Leggi l'articolo →