REST API's bouwen in Go: complete handleiding
Bouw productieklare REST-API’s met het robuuste ecosysteem van Go
Het bouwen van hoogwaardige REST-API’s met Go is een standaardbenadering geworden voor het aandrijven van systemen bij Google, Uber, Dropbox en talloze startups.
De eenvoud van Go, de sterke ondersteuning van concurrentie en de snelle compilatietijd maken het ideaal voor microservices en backend-ontwikkeling.
Deze geweldige afbeelding is gegenereerd door FLUX.1-Kontext-dev: Image Augmentation AI Model.
Waarom Go voor API-ontwikkeling?
Go biedt verschillende overtuigende voordelen voor API-ontwikkeling:
Prestatie en Efficiëntie: Go compileert naar native machinecode, wat bijna C-prestaties oplevert zonder de complexiteit. Het efficiëte geheugenbeheer en de kleine binairgrootte maken het perfect voor container-gedreven deployments.
Ingebouwde Concurrentie: Goroutines en channels maken het afhandelen van duizenden gelijktijdige verzoeken eenvoudig. Je kunt meerdere API-aanroepen tegelijk verwerken zonder complexe threading-code.
Sterke Standaardbibliotheek: Het net/http-pakket biedt een productieklare HTTP-server direct uit de doos. Je kunt complete API’s bouwen zonder externe afhankelijkheden.
Snelle Compilatie: De compilatiesnelheid van Go stelt je in staat tot snelle iteratie tijdens de ontwikkeling. Grote projecten compileren in seconden, niet in minuten.
Statische Typing met Eenvoud: Het typesysteem van Go vangt fouten op compileer-time op en behoudt tegelijkertijd de helderheid van de code. De taal heeft een klein functieset dat snel te leren is.
Benaderingen voor het bouwen van API’s in Go
Gebruik van de Standaardbibliotheek
De standaardbibliotheek van Go biedt alles wat nodig is voor basis API-ontwikkeling. Hier is een minimaal voorbeeld:
package main
import (
"encoding/json"
"log"
"net/http"
)
type Response struct {
Message string `json:"message"`
Status int `json:"status"`
}
func healthHandler(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Type", "application/json")
json.NewEncoder(w).Encode(Response{
Message: "API is healthy",
Status: 200,
})
}
func main() {
http.HandleFunc("/health", healthHandler)
log.Println("Server starting on :8080")
log.Fatal(http.ListenAndServe(":8080", nil))
}
Deze aanpak biedt volledige controle en nul afhankelijkheden. Het is ideaal voor eenvoudige API’s of wanneer je HTTP-behandeling op fundamenteel niveau wilt begrijpen.
Populaire Go Webframeworks
Hoewel de standaardbibliotheek krachtig is, kunnen frameworks de ontwikkeling versnellen:
Gin: Het meest populaire Go webframework, bekend om zijn prestaties en gebruiksgemak. Het biedt handig routing, middleware-ondersteuning en validatie van verzoeken.
package main
import (
"github.com/gin-gonic/gin"
"net/http"
)
func main() {
r := gin.Default()
r.GET("/users/:id", func(c *gin.Context) {
id := c.Param("id")
c.JSON(http.StatusOK, gin.H{
"user_id": id,
"name": "John Doe",
})
})
r.Run(":8080")
}
Chi: Een lichtgewicht, idiomatische router die voelt als een uitbreiding van de standaardbibliotheek. Het is bijzonder goed voor het bouwen van RESTful services met genest routing.
Echo: Hoogwaardig framework met uitgebreide middleware en uitstekende documentatie. Het is geoptimaliseerd voor snelheid en blijft toch ontwikkelaar-vriendelijk.
Fiber: Geïnspireerd door Express.js, gebouwd bovenop Fasthttp. Het is de snelste optie, maar gebruikt een andere HTTP-implementatie dan de standaardbibliotheek.
Architectuurpatronen
Bij het werken met database-operaties in Go, zul je je ORM-strategie moeten overwegen. Verschillende projecten hebben benaderingen vergeleken zoals GORM, Ent, Bun en sqlc, elk met verschillende afwegingen tussen ontwikkelaarsproductiviteit en prestaties.
Gelaagde Architectuur
Structureer je API met een duidelijke scheiding van concerns:
// Handler Layer - HTTP concerns
type UserHandler struct {
service *UserService
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
id := chi.URLParam(r, "id")
user, err := h.service.GetByID(r.Context(), id)
if err != nil {
respondError(w, err)
return
}
respondJSON(w, user)
}
// Service Layer - Business logic
type UserService struct {
repo *UserRepository
}
func (s *UserService) GetByID(ctx context.Context, id string) (*User, error) {
// Validate, transform, apply business rules
return s.repo.FindByID(ctx, id)
}
// Repository Layer - Data access
type UserRepository struct {
db *sql.DB
}
func (r *UserRepository) FindByID(ctx context.Context, id string) (*User, error) {
// Database query implementation
}
Deze scheiding maakt testen easier en houdt je code onderhoudbaar naarmate het project groeit.
Domain-Driven Design
Voor complexe toepassingen kun je overwegen om code te organiseren op domein in plaats van technische lagen. Elke domein-pakket bevat zijn eigen modellen, services en repositories.
Als je multi-tenant applicaties bouwt, wordt het begrijpen van databasepatronen voor multi-tenancy cruciaal voor je API-architectuur.
Verzoeken Afhandelen en Validatie
Inputvalidatie
Valideer altijd inkomende data voordat je deze verwerkt:
type CreateUserRequest struct {
Email string `json:"email" validate:"required,email"`
Username string `json:"username" validate:"required,min=3,max=50"`
Age int `json:"age" validate:"gte=0,lte=150"`
}
func (h *UserHandler) CreateUser(w http.ResponseWriter, r *http.Request) {
var req CreateUserRequest
if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
respondError(w, NewBadRequestError("Invalid JSON"))
return
}
validate := validator.New()
if err := validate.Struct(req); err != nil {
respondError(w, NewValidationError(err))
return
}
// Process valid request
}
Het go-playground/validator-pakket biedt uitgebreide validatieregels en aangepaste validators.
Verzoekcontext
Gebruik context voor waarden die gebonden zijn aan het verzoek en voor annulering:
func authMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
token := r.Header.Get("Authorization")
userID, err := validateToken(token)
if err != nil {
http.Error(w, "Unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), "userID", userID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
Voor een diepgaande duik in context best practices — inclusief getypte keys, propagatie van annulering, timeout-budgetten en graceful shutdown — zie Go context.Context Done Right.
Authenticatie en Beveiliging
JWT-gebaseerde Authenticatie
JSON Web Tokens bieden stateless authenticatie:
import "github.com/golang-jwt/jwt/v5"
func generateToken(userID string) (string, error) {
claims := jwt.MapClaims{
"user_id": userID,
"exp": time.Now().Add(time.Hour * 24).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString([]byte(os.Getenv("JWT_SECRET")))
}
func validateToken(tokenString string) (string, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
return []byte(os.Getenv("JWT_SECRET")), nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims["user_id"].(string), nil
}
return "", err
}
Middleware-patronen
Implementeer dwarsdoorsnedeproblemen (cross-cutting concerns) als middleware:
func loggingMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
log.Printf("Started %s %s", r.Method, r.URL.Path)
next.ServeHTTP(w, r)
log.Printf("Completed in %v", time.Since(start))
})
}
func rateLimitMiddleware(next http.Handler) http.Handler {
limiter := rate.NewLimiter(10, 20) // 10 requests/sec, burst of 20
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
if !limiter.Allow() {
http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
return
}
next.ServeHTTP(w, r)
})
}
Foutafhandeling
Implementeer consistente foutreacties:
type APIError struct {
Code int `json:"code"`
Message string `json:"message"`
Details string `json:"details,omitempty"`
}
func (e *APIError) Error() string {
return e.Message
}
func NewBadRequestError(message string) *APIError {
return &APIError{
Code: http.StatusBadRequest,
Message: message,
}
}
func NewNotFoundError(resource string) *APIError {
return &APIError{
Code: http.StatusNotFound,
Message: fmt.Sprintf("%s not found", resource),
}
}
func respondError(w http.ResponseWriter, err error) {
apiErr, ok := err.(*APIError)
if !ok {
apiErr = &APIError{
Code: http.StatusInternalServerError,
Message: "Internal server error",
}
// Log the actual error for debugging
log.Printf("Unexpected error: %v", err)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(apiErr.Code)
json.NewEncoder(w).Encode(apiErr)
}
Voor een dieper inzicht in foutarchitectuur over repository-, service- en handlerlagen — inclusief sentinel errors, aangepaste fouttypes, boundary translation en veilige response mapping — zie Go Error Handling Architecture: Boundaries and Patterns.
Database-integratie
Verbindingsbeheer
Gebruik connection pooling voor efficiëte database-toegang:
func initDB() (*sql.DB, error) {
db, err := sql.Open("postgres", os.Getenv("DATABASE_URL"))
if err != nil {
return nil, err
}
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(5)
db.SetConnMaxLifetime(5 * time.Minute)
return db, db.Ping()
}
Query-patronen
Gebruik prepared statements en context voor veilige database-operaties:
func (r *UserRepository) FindByEmail(ctx context.Context, email string) (*User, error) {
query := `SELECT id, email, username, created_at FROM users WHERE email = $1`
var user User
err := r.db.QueryRowContext(ctx, query, email).Scan(
&user.ID,
&user.Email,
&user.Username,
&user.CreatedAt,
)
if err == sql.ErrNoRows {
return nil, ErrUserNotFound
}
return &user, err
}
Teststrategieën
Handler-testen
Test HTTP-handlers met behulp van httptest:
func TestGetUserHandler(t *testing.T) {
// Setup
mockService := &MockUserService{
GetByIDFunc: func(ctx context.Context, id string) (*User, error) {
return &User{ID: "1", Username: "testuser"}, nil
},
}
handler := &UserHandler{service: mockService}
// Execute
req := httptest.NewRequest("GET", "/users/1", nil)
w := httptest.NewRecorder()
handler.GetUser(w, req)
// Assert
assert.Equal(t, http.StatusOK, w.Code)
var response User
json.Unmarshal(w.Body.Bytes(), &response)
assert.Equal(t, "testuser", response.Username)
}
Integratietesten
Test complete workflows met een testdatabase:
func TestCreateUserEndToEnd(t *testing.T) {
// Setup test database
db := setupTestDB(t)
defer db.Close()
// Start test server
server := setupTestServer(db)
defer server.Close()
// Make request
body := strings.NewReader(`{"email":"test@example.com","username":"testuser"}`)
resp, err := http.Post(server.URL+"/users", "application/json", body)
require.NoError(t, err)
defer resp.Body.Close()
// Verify response
assert.Equal(t, http.StatusCreated, resp.StatusCode)
// Verify database state
var count int
db.QueryRow("SELECT COUNT(*) FROM users WHERE email = $1", "test@example.com").Scan(&count)
assert.Equal(t, 1, count)
}
API-documentatie
OpenAPI/Swagger
Documenteer je API met OpenAPI-specificaties:
// @title User API
// @version 1.0
// @description API for managing users
// @host localhost:8080
// @BasePath /api/v1
// @Summary Get user by ID
// @Description Retrieves a user's information by their ID
// @Tags users
// @Accept json
// @Produce json
// @Param id path string true "User ID"
// @Success 200 {object} User
// @Failure 404 {object} APIError
// @Router /users/{id} [get]
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
// Implementation
}
Gebruik swaggo/swag om interactieve API-documentatie te genereren uit deze comments.
Prestatieoptimalisatie
Response-compressie
Schakel gzip-compressie in voor responses:
import "github.com/NYTimes/gziphandler"
func main() {
r := chi.NewRouter()
r.Use(gziphandler.GzipHandler)
// Rest of setup
}
Caching
Implementeer caching voor vaak toegewezen data:
import "github.com/go-redis/redis/v8"
type CachedUserRepository struct {
repo *UserRepository
cache *redis.Client
}
func (r *CachedUserRepository) GetByID(ctx context.Context, id string) (*User, error) {
// Try cache first
cached, err := r.cache.Get(ctx, "user:"+id).Result()
if err == nil {
var user User
json.Unmarshal([]byte(cached), &user)
return &user, nil
}
// Cache miss - fetch from database
user, err := r.repo.FindByID(ctx, id)
if err != nil {
return nil, err
}
// Store in cache
data, _ := json.Marshal(user)
r.cache.Set(ctx, "user:"+id, data, 10*time.Minute)
return user, nil
}
Connection Pooling
Herbruik HTTP-verbindingen voor externe API-aanroepen:
var httpClient = &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
}
Overwegingen bij Deployment
Docker-containerisatie
Maak efficiëte Docker-images met behulp van multi-stage builds:
# Build stage
FROM golang:1.21-alpine AS builder
WORKDIR /app
COPY go.mod go.sum ./
RUN go mod download
COPY . .
RUN CGO_ENABLED=0 GOOS=linux go build -o api ./cmd/api
# Production stage
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/api .
EXPOSE 8080
CMD ["./api"]
Dit resulteert in een minimale image (typisch onder de 20MB) met alleen je binary en essentiële certificaten.
Configuratiebeheer
Gebruik omgevingsvariabelen en configuratiebestanden:
type Config struct {
Port string
DatabaseURL string
JWTSecret string
LogLevel string
}
func LoadConfig() (*Config, error) {
return &Config{
Port: getEnv("PORT", "8080"),
DatabaseURL: getEnv("DATABASE_URL", ""),
JWTSecret: getEnv("JWT_SECRET", ""),
LogLevel: getEnv("LOG_LEVEL", "info"),
}, nil
}
func getEnv(key, defaultValue string) string {
if value := os.Getenv(key); value != "" {
return value
}
return defaultValue
}
Graceful Shutdown
Verwerk shutdown-signalen correct:
func main() {
server := &http.Server{
Addr: ":8080",
Handler: setupRouter(),
}
// Start server in goroutine
go func() {
if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
log.Fatalf("Server error: %v", err)
}
}()
// Wait for interrupt signal
quit := make(chan os.Signal, 1)
signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
<-quit
log.Println("Shutting down server...")
// Give outstanding requests 30 seconds to complete
ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
defer cancel()
if err := server.Shutdown(ctx); err != nil {
log.Fatalf("Server forced to shutdown: %v", err)
}
log.Println("Server exited")
}
Monitoring en Observability
Gestructureerde Logging
Gebruik gestructureerde logging voor betere zoekbaarheid:
import "go.uber.org/zap"
func setupLogger() (*zap.Logger, error) {
config := zap.NewProductionConfig()
config.OutputPaths = []string{"stdout"}
return config.Build()
}
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
logger := h.logger.With(
zap.String("method", r.Method),
zap.String("path", r.URL.Path),
zap.String("user_id", r.Context().Value("userID").(string)),
)
logger.Info("Processing request")
// Handler logic
}
Zap is een solide keuze als je een volwassen third-party logger wilt. Als je de voorkeur geeft aan de standaardbibliotheek, biedt log/slog (Go 1.21+) JSON-vriendelijke records, redactie op handler-niveau en velden die overeenkomen met traces en log-pipelines. Zie Structured Logging in Go with slog for Observability and Alerting.
Metingverzameling
Expose Prometheus-metingen:
import "github.com/prometheus/client_golang/prometheus"
var (
requestDuration = prometheus.NewHistogramVec(
prometheus.HistogramOpts{
Name: "http_request_duration_seconds",
Help: "Duration of HTTP requests",
},
[]string{"method", "path", "status"},
)
)
func init() {
prometheus.MustRegister(requestDuration)
}
func metricsMiddleware(next http.Handler) http.Handler {
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
start := time.Now()
recorder := &statusRecorder{ResponseWriter: w, status: 200}
next.ServeHTTP(recorder, r)
duration := time.Since(start).Seconds()
requestDuration.WithLabelValues(
r.Method,
r.URL.Path,
strconv.Itoa(recorder.status),
).Observe(duration)
})
}
Geavanceerde Patronen
Werken met Gestructureerde Output
Bij het bouwen van API’s die integreren met LLM’s, moet je soms responses beperken met gestructureerde output. Dit is bijzonder nuttig voor AI-gebaseerde functies in je API.
Web Scraping voor API-datbronnen
Als je API data moet aggregeren van andere websites, kan het begrijpen van alternatieven voor Beautiful Soup in Go je helpen robuuste web scraping-functionaliteit te implementeren.
Documentgeneratie
Veel API’s moeten documenten genereren. Voor PDF-generatie in Go zijn er verschillende libraries en benaderingen die je kunt integreren in je API-eindpunten.
Semantische Zoeken en Reranking
Voor API’s die text search en retrieval behandelen, kan het implementeren van reranking met embedding models de relevantie van zoekresultaten aanzienlijk verbeteren.
MCP Servers Bouwen
Als je API’s implementeert die het Model Context Protocol volgen, bekijk dan deze gids over het implementeren van MCP servers in Go, die protocol-specificaties en praktische implementaties dekt.
Veelvoorkomende Valkuilen en Oplossingen
Context Niet Correct Gebruiken
Geef context altijd door en eerbiedig deze door je hele call chain. Dit stelt je in staat tot correcte annulering en timeout-behandeling.
Goroutine Leaks Ignoreren
Zorg ervoor dat alle goroutines kunnen eindigen. Gebruik contexten met deadlines en heb altijd een manier om voltooiing te signaleren.
Slechte Foutafhandeling
Retourneer geen ruwe database-fouten naar clients. Wrap errors met context en retourneer gesaniteerde berichten in API-responses.
Ontbrekende Inputvalidatie
Valideer alle inputs op het entry point. Vertrouw nooit client-data, zelfs niet van geauthenticeerde gebruikers.
Onvoldoende Testen
Test niet alleen de happy path. Dek foutgevallen, randvoorwaarden en scenario’s voor gelijktijdige toegang af.
Samenvatting van Best Practices
-
Begin Eenvoudig: Begin met de standaardbibliotheek. Voeg frameworks toe wanneer complexiteit dit vereist.
-
Laag je Applicatie: Scheid HTTP-handlers, businesslogic en data-toegang voor onderhoudbaarheid.
-
Valideer Alles: Controleer inputs op grenzen. Gebruik strong typing en validatiebibliotheken.
-
Handel Fouten Consistent Af: Retourneer gestructureerde foutreacties. Log interne fouten maar exposeer ze niet.
-
Gebruik Middleware: Implementeer dwarsdoorsnedeproblemen (auth, logging, metingen) als middleware.
-
Test Thoroughly: Schrijf unit tests voor logica, integratietests voor data-toegang en end-to-end tests voor workflows.
-
Documenteer je API: Gebruik OpenAPI/Swagger voor interactieve documentatie.
-
Monitor Productie: Implementeer gestructureerde logging, metingverzameling en health checks.
-
Optimaliseer Zorgvuldig: Profileer voordat je optimaliseert. Gebruik caching, connection pooling en compressie waar nuttig.
-
Ontwerp voor Graceful Shutdown: Verwerk terminatiesignalen en drain connections correct.
Checklist voor Starten
Als referentie bij het werken aan Go-projecten, kan het handig zijn om een comprehensive Go cheatsheet bij de hand te hebben om ontwikkeling te versnellen en als snelle referentie voor syntax en veelvoorkomende patronen te dienen.
Klaar om je eerste Go API te bouwen? Begin met deze stappen:
- ✅ Stel je Go-omgeving en projectstructuur in
- ✅ Kies tussen standaardbibliotheek of een framework
- ✅ Implementeer basis CRUD-eindpunten
- ✅ Voeg requestvalidatie en foutafhandeling toe
- ✅ Implementeer authenticatiemiddleware
- ✅ Voeg database-integratie toe met connection pooling
- ✅ Schrijf unit- en integratietests
- ✅ Voeg API-documentatie toe
- ✅ Implementeer logging en metingen
- ✅ Containeriseer met Docker
- ✅ Stel CI/CD-pipeline in
- ✅ Deploy naar productie met monitoring
Conclusie
Go biedt een uitstekende basis voor het bouwen van REST-API’s, waarbij prestaties, eenvoud en robuuste tooling worden gecombineerd. Of je nu microservices, interne tools of publieke API’s bouwt, het Go-ecosysteem heeft volwassen oplossingen voor elke vereiste.
De sleutel tot succes is beginnen met solide architectuurpatronen, correcte foutafhandeling en validatie vanaf het begin implementeren en uitgebreide testcoverage bouwen. Naarmate je API groeit, zullen de prestatiekenmerken van Go en de sterke concurrentieondersteuning je goed van dienst zijn.
Onthoud dat API-ontwikkeling iteratief is. Begin met een minimale levensvatbare implementatie, verzamel feedback en verfijn je aanpak op basis van gebruikspatronen in de echte wereld. De snelle compilatie van Go en de eenvoudige refactoring maken deze iteratiecyclus soepel en productief.
Nuttige Links
- Go Cheat Sheet
- Structured Logging in Go with slog for Observability and Alerting
- Comparing Go ORMs for PostgreSQL: GORM vs Ent vs Bun vs sqlc
- Multi-Tenancy Database Patterns with examples in Go
- Beautiful Soup Alternatives for Go
- Generating PDF in GO - Libraries and examples
- Constraining LLMs with Structured Output: Ollama, Qwen3 & Python or Go
- Reranking text documents with Ollama and Qwen3 Embedding model - in Go
- Model Context Protocol (MCP), and notes on implementing MCP server in Go
Externe Bronnen
Officiële Documentatie
- Go Official Documentation - De officiële Go-documentatie en tutorials
- Go net/http Package - Documentatie voor het standaardbibliotheek HTTP-pakket
- Effective Go - Best practices voor het schrijven van helder, idiomatisch Go-code
Populaire Frameworks en Bibliotheken
- Gin Web Framework - Snel HTTP webframework met uitgebreide functies
- Chi Router - Lichtgewicht, idiomatische router voor het bouwen van Go HTTP-services
- Echo Framework - Hoogwaardig, uitbreidbaar, minimalistisch webframework
- Fiber Framework - Express-geïnspireerd webframework gebouwd op Fasthttp
- GORM - De fantastische ORM-bibliotheek voor Golang
- golang-jwt - JWT-implementatie voor Go
Test- en Ontwikkeltools
- Testify - Een toolkit met veelvoorkomende assertions en mocks
- httptest Package - Standaardbibliotheek utilities voor HTTP-testen
- Swaggo - Automatisch genereren van RESTful API-documentatie
- Air - Live reload voor Go-apps tijdens ontwikkeling
Best Practices en Gidsen
- Go Project Layout - Standaard Go-projectlayouts
- Uber Go Style Guide - Uitgebreide Go-stijlgids van Uber
- Go Code Review Comments - Veelvoorkomente commentaren tijdens Go-code reviews
- REST API Design Best Practices - Algemene REST API-ontwerpprincipes
Beveiliging en Authenticatie
- OWASP Go Secure Coding Practices - Beveiligingsrichtlijnen voor Go-applicaties
- OAuth2 for Go - OAuth 2.0-implementatie
- bcrypt Package - Password hashing-implementatie
Prestaties en Monitoring
- pprof - Ingebouwd profileringstool voor Go-programma’s
- Prometheus Client - Prometheus-instrumentatiebibliotheek voor Go
- Zap Logger - Snel, gestructureerd, geniveaud logging
- App Architecture hub — API design, code structure, and integration patterns