Tworzenie interfejsów API REST w Go: Kompletny przewodnik

Twórz gotowe do produkcji API REST z wykorzystaniem solidnego ekosystemu Go

Page content

Tworzenie wysokiej wydajności REST API z Go stało się standardowym podejściem do napędzania systemów w Google, Uber, Dropbox i licznych start-upach.

Prosta konstrukcja Go, silna obsługa współbieżności i szybka kompilacja czynią z niego idealny wybór do tworzenia mikroserwisów i rozwoju backendu.

go api To wspaniałe zdjęcie zostało wygenerowane przez FLUX.1-Kontext-dev: Model AI do Augmentacji Obrazu.

Dlaczego Go do tworzenia API?

Go przynosi wiele przekonujących zalet do tworzenia API:

Wydajność i wydajność: Go kompiluje się do kodu maszynowego, zapewniając wydajność zbliżoną do C bez skomplikowania. Efektywna zarządzanie pamięcią i małe rozmiary binarnej czynią z niego idealny wybór do wdrożeń w kontenerach.

Wbudowana współbieżność: Goroutines i kanały ułatwiają obsługę tysięcy żądań współbieżnych. Można przetwarzać wiele wywołań API jednocześnie bez skomplikowanego kodu wątkowego.

Silna biblioteka standardowa: Pakiet net/http oferuje gotowy do użycia serwer HTTP. Można zbudować pełne API bez żadnych zależności zewnętrznych.

Szybka kompilacja: Szybka kompilacja Go umożliwia szybkie iteracje podczas rozwoju. Duże projekty kompilują się w sekundach, a nie minutach.

Statyczne typowanie z prostotą: System typów Go wykrywa błędy w czasie kompilacji, jednocześnie zachowując przejrzystość kodu. Język ma małą liczbę funkcji, które są szybko do nauczenia.

Metody tworzenia API w Go

Używanie biblioteki standardowej

Biblioteka standardowa Go oferuje wszystko, co jest potrzebne do podstawowego rozwoju API. Oto przykład minimalny:

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 jest zdrowe",
        Status:  200,
    })
}

func main() {
    http.HandleFunc("/health", healthHandler)
    log.Println("Uruchamianie serwera na porcie :8080")
    log.Fatal(http.ListenAndServe(":8080", nil))
}

Ten podejście oferuje pełną kontrolę i zero zależności. Jest idealny do prostych API lub gdy chcesz zrozumieć obsługę HTTP na podstawowym poziomie.

Popularne frameworki webowe w Go

Choć biblioteka standardowa jest potężna, frameworki mogą przyspieszyć rozwój:

Gin: Najpopularniejszy framework webowy w Go, znany z wydajności i łatwości użycia. Oferuje wygodne routing, obsługę middleware i walidację żądań.

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: Lekki, idiomiczny router, który czuje się jak rozszerzenie biblioteki standardowej. Jest szczególnie dobry do budowania usług REST z zagnieżdżonym routingiem.

Echo: Wysokowydajny framework z rozszerzoną obsługą middleware i wspaniałą dokumentacją. Jest zoptymalizowany pod kątem prędkości, jednocześnie pozostając przyjaznym dla programistów.

Fiber: Wzorowany na Express.js, zbudowany na Fasthttp. Jest najbardziej szybkim wyborem, ale używa innego implementacji HTTP niż biblioteka standardowa.

Architektura

Pracując z operacjami na bazach danych w Go, musisz rozważyć strategię ORM. Różne projekty porównywały podejścia takie jak GORM, Ent, Bun i sqlc, które oferują różne kompromisy między wydajnością a produktywnością programisty.

Warstwowa architektura

Zorganizuj swój API z jasnym oddzieleniem obowiązków:

// Warstwa Handlera - koncerny HTTP
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)
}

// Warstwa Usługi - logika biznesowa
type UserService struct {
    repo *UserRepository
}

func (s *UserService) GetByID(ctx context.Context, id string) (*User, error) {
    // Walidacja, transformacja, zastosowanie reguł biznesowych
    return s.repo.FindByID(ctx, id)
}

// Warstwa Repozytorium - dostęp do danych
type UserRepository struct {
    db *sql.DB
}

func (r *UserRepository) FindByID(ctx context.Context, id string) (*User, error) {
    // Implementacja zapytania do bazy danych
}

To oddzielenie ułatwia testowanie i utrzymuje kod w utrzymaniu, gdy projekt rośnie.

Projektowanie oparte na domenie

Dla złożonych aplikacji rozważ organizowanie kodu według domeny zamiast technicznych warstw. Każdy pakiet domeny zawiera własne modele, usługi i repozytoria.

Jeśli tworzysz aplikacje wielodostępowe, zrozumienie wzorców baz danych dla wielodostępności staje się kluczowe dla architektury API.

Obsługa żądań i walidacja

Walidacja danych wejściowych

Zawsze waliduj przychodzące dane przed przetwarzaniem:

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("Nieprawidłowy JSON"))
        return
    }
    
    validate := validator.New()
    if err := validate.Struct(req); err != nil {
        respondError(w, NewValidationError(err))
        return
    }
    
    // Przetwarzanie poprawnego żądania
}

Pakiet go-playground/validator oferuje szerokie zasady walidacji i walidatory niestandardowe.

Kontekst żądania

Używaj kontekstu dla wartości zakresu żądania i anulowania:

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, "Nieautoryzowany", http.StatusUnauthorized)
            return
        }
        
        ctx := context.WithValue(r.Context(), "userID", userID)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

Autoryzacja i bezpieczeństwo

Autoryzacja oparta na JWT

JSON Web Tokens oferują bezstanową autoryzację:

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
}

Wzorce middleware

Zaimplementuj zagadnienia przekroczne jako middleware:

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        start := time.Now()
        log.Printf("Rozpoczęto %s %s", r.Method, r.URL.Path)
        
        next.ServeHTTP(w, r)
        
        log.Printf("Zakończono w %v", time.Since(start))
    })
}

func rateLimitMiddleware(next http.Handler) http.Handler {
    limiter := rate.NewLimiter(10, 20) // 10 żądań/sec, wstrzymanie 20
    
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if !limiter.Allow() {
            http.Error(w, "Przekroczono limit przepustowości", http.StatusTooManyRequests)
            return
        }
        next.ServeHTTP(w, r)
    })
}

Obsługa błędów

Zaimplementuj spójne odpowiedzi na błędy:

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) *API错误 {
    return &APIError{
        Code:    http.StatusNotFound,
        Message: fmt.Sprintf("%s nie znaleziono", resource),
    }
}

func respondError(w http.ResponseWriter, err error) {
    apiErr, ok := err.(*APIError)
    if !ok {
        apiErr = &APIError{
            Code:    http.StatusInternalServerError,
            Message: "Wewnętrzny błąd serwera",
        }
        // Zaloguj rzeczywisty błąd dla debugowania
        log.Printf("Nieoczekiwany błąd: %v", err)
    }
    
    w.Header().Set("Content-Type", "application/json")
    w.WriteHeader(apiErr.Code)
    json.NewEncoder(w).Encode(apiErr)
}

Integracja z bazą danych

Zarządzanie połączeniami

Używaj puli połączeń dla wydajnego dostępu do bazy danych:

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()
}

Wzorce zapytań

Używaj przygotowanych instrukcji i kontekstu dla bezpiecznych operacji na bazie danych:

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
}

Strategie testowania

Testowanie handlerów

Testuj handlerów HTTP za pomocą httptest:

func TestGetUserHandler(t *testing.T) {
    // Ustawienie
    mockService := &MockUserService{
        GetByIDFunc: func(ctx context.Context, id string) (*User, error) {
            return &User{ID: "1", Username: "testuser"}, nil
        },
    }
    handler := &UserHandler{service: mockService}
    
    // Wykonanie
    req := httptest.NewRequest("GET", "/users/1", nil)
    w := httptest.NewRecorder()
    handler.GetUser(w, req)
    
    // Sprawdzenie
    assert.Equal(t, http.StatusOK, w.Code)
    
    var response User
    json.Unmarshal(w.Body.Bytes(), &response)
    assert.Equal(t, "testuser", response.Username)
}

Testowanie integracji

Testuj pełne scenariusze z użyciem testowej bazy danych:

func TestCreateUserEndToEnd(t *testing.T) {
    // Ustawienie testowej bazy danych
    db := setupTestDB(t)
    defer db.Close()
    
    // Uruchomienie testowego serwera
    server := setupTestServer(db)
    defer server.Close()
    
    // Wysłanie żądania
    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()
    
    // Sprawdzenie odpowiedzi
    assert.Equal(t, http.StatusCreated, resp.StatusCode)
    
    // Sprawdzenie stanu bazy danych
    var count int
    db.QueryRow("SELECT COUNT(*) FROM users WHERE email = $1", "test@example.com").Scan(&count)
    assert.Equal(t, 1, count)
}

Dokumentacja API

OpenAPI/Swagger

Dokumentuj swój API za pomocą specyfikacji OpenAPI:

// @title User API
// @version 1.0
// @description API do zarządzania użytkownikami
// @host localhost:8080
// @BasePath /api/v1

// @Summary Pobierz użytkownika po ID
// @Description Pobiera informacje o użytkowniku po jego ID
// @Tags użytkownicy
// @Accept json
// @Produce json
// @Param id path string true "ID użytkownika"
// @Success 200 {object} User
// @Failure 404 {object} APIError
// @Router /users/{id} [get]
func (h *UserHandler) GetUser(w http.ResponseWriter, r *http.Request) {
    // Implementacja
}

Użyj swaggo/swag, aby wygenerować interaktywną dokumentację API z tych komentarzy.

Optymalizacja wydajności

Skompresowanie odpowiedzi

Włącz kompresję gzip dla odpowiedzi:

import "github.com/NYTimes/gziphandler"

func main() {
    r := chi.NewRouter()
    r.Use(gziphandler.GzipHandler)
    // Pozostała konfiguracja
}

Caching

Zaimplementuj caching dla często odwiedzanych danych:

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) {
    // Spróbuj najpierw cache
    cached, err := r.cache.Get(ctx, "user:"+id).Result()
    if err == nil {
        var user User
        json.Unmarshal([]byte(cached), &user)
        return &user, nil
    }
    
    // Brak w cache - pobierz z bazy danych
    user, err := r.repo.FindByID(ctx, id)
    if err != nil {
        return nil, err
    }
    
    // Zapisz w cache
    data, _ := json.Marshal(user)
    r.cache.Set(ctx, "user:"+id, data, 10*time.Minute)
    
    return user, nil
}

Puli połączeń

Odnawiaj połączenia HTTP dla wywołań do zewnętrznych API:

var httpClient = &http.Client{
    Timeout: 10 * time.Second,
    Transport: &http.Transport{
        MaxIdleConns:        100,
        MaxIdleConnsPerHost: 10,
        IdleConnTimeout:     90 * time.Second,
    },
}

Rozważenia dotyczące wdrażania

Konteneryzacja za pomocą Docker

Twórz wydajne obrazy Docker za pomocą wielofazowych budów:

# Faza budowania
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

# Faza produkcyjna
FROM alpine:latest
RUN apk --no-cache add ca-certificates
WORKDIR /root/
COPY --from=builder /app/api .
EXPOSE 8080
CMD ["./api"]

To tworzy minimalny obraz (zwykle poniżej 20MB) z tylko Twoim binarikiem i niezbędnymi certyfikatami.

Zarządzanie konfiguracją

Używaj zmiennych środowiskowych i plików konfiguracyjnych:

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
}

Zakończenie pracy w sposób łagodny

Poprawnie obsługuj sygnały zakończenia:

func main() {
    server := &http.Server{
        Addr:    ":8080",
        Handler: setupRouter(),
    }
    
    // Uruchom serwer w goroutine
    go func() {
        if err := server.ListenAndServe(); err != nil && err != http.ErrServerClosed {
            log.Fatalf("Błąd serwera: %v", err)
        }
    }()
    
    // Oczekiwanie na sygnał przerwania
    quit := make(chan os.Signal, 1)
    signal.Notify(quit, syscall.SIGINT, syscall.SIGTERM)
    <-quit
    
    log.Println("Zamykanie serwera...")
    
    // Daj żądanym żądaniami 30 sekund, aby ukończyć
    ctx, cancel := context.WithTimeout(context.Background(), 30*time.Second)
    defer cancel()
    
    if err := server.Shutdown(ctx); err != nil {
        log.Fatalf("Serwer został zmuszony do zakończenia: %v", err)
    }
    
    log.Println("Serwer wygasł")
}

Monitorowanie i obserwowalność

Strukturalne logowanie

Używaj strukturalnego logowania dla lepszej przeszukiwalności:

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("Przetwarzanie żądania")
    // Logika handlera
}

Zbieranie metryk

Wystaw metryki Prometheus:

import "github.com/prometheus/client_golang/prometheus"

var (
    requestDuration = prometheus.NewHistogramVec(
        prometheus.HistogramOpts{
            Name: "http_request_duration_seconds",
            Help: "Czas trwania żądań HTTP",
        },
        []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)
    })
}

Zaawansowane wzorce

Pracowanie z strukturalnym wyjściem

Gdy budujesz API, które integruje się z LLM, możesz potrzebować ograniczenia odpowiedzi z użyciem strukturalnego wyjścia. To szczególnie przydatne jest dla funkcji AI w Twoim API.

Scraping sieci dla źródeł danych API

Jeśli Twoje API potrzebuje agregacji danych z innych stron internetowych, zrozumienie alternatyw dla Beautiful Soup w Go może pomóc w implementacji solidnej funkcjonalności scrapingu sieci.

Generowanie dokumentów

Wiele API potrzebuje generowania dokumentów. Dla generowania PDF w Go, są kilka bibliotek i podejść, które możesz zintegrować z końcami API.

Semanticzne wyszukiwanie i ponowne rankowanie

Dla API, które zajmują się wyszukiwaniem i odzyskiwaniem tekstu, implementowanie ponownego rankowania z modelami embeddingu może znacząco poprawić relevantność wyników wyszukiwania.

Budowanie serwerów MCP

Jeśli implementujesz API, które przestrzega Model Context Protocol, sprawdź tę wskazówkę dotyczącą implementacji serwerów MCP w Go, która obejmuje specyfikacje protokołu i praktyczne implementacje.

Powszechne pułapki i rozwiązania

Nieprawidłowe używanie kontekstów

Zawsze przekazuj i szanuj kontekst w całym łańcuchu wywołań. To umożliwia właściwe anulowanie i obsługa limitów czasu.

Ignorowanie przecieków goroutines

Upewnij się, że wszystkie goroutines mogą zostać zakończone. Używaj kontekstów z terminami i zawsze masz sposób na sygnalizację zakończenia.

Niewystarczająca obsługa błędów

Nie zwracaj surowych błędów bazy danych do klientów. Ogranicz błędy z kontekstem i zwracaj wyczyścione komunikaty w odpowiedziach API.

Brak walidacji danych wejściowych

Waliduj wszystkie dane wejściowe na granicy. Nigdy nie zaufaj danym klienta, nawet od uwierzytelnionych użytkowników.

Niewystarczające testowanie

Nie testuj tylko przypadków idealnych. Pokryj przypadki błędów, warunki graniczne i scenariusze dostępu współbieżnego.

Podsumowanie najlepszych praktyk

  1. Zacznij od prostego: Zacznij od biblioteki standardowej. Dodaj frameworky, gdy złożoność tego wymaga.

  2. Warstwuj aplikację: Oddziel obsługę HTTP, logikę biznesową i dostęp do danych dla utrzymanialności.

  3. Waliduj wszystko: Sprawdzaj dane wejściowe na granicy. Używaj silnego typowania i bibliotek walidacyjnych.

  4. Zachowuj spójną obsługę błędów: Zwracaj strukturalne odpowiedzi na błędy. Loguj błędy wewnętrzne, ale nie wyjawiaj ich.

  5. Używaj middleware: Implementuj zagadnienia przekroczne (autoryzacja, logowanie, metryki) jako middleware.

  6. Testuj dokładnie: Pisz testy jednostkowe dla logiki, testy integracyjne dla dostępu do danych i testy end-to-end dla scenariuszy.

  7. Dokumentuj swój API: Używaj OpenAPI/Swagger do interaktywnej dokumentacji.

  8. Monitoruj produkcję: Implementuj strukturalne logowanie, zbieranie metryk i kontrole zdrowia.

  9. Optymalizuj ostrożnie: Profiluj przed optymalizacją. Używaj cachingu, puli połączeń i kompresji tam, gdzie to korzystne.

  10. Projektuj na łagodne wygaszanie: Obsługuj sygnały zakończenia i poprawnie wygaszaj połączenia.

Lista sprawdzania przygotowania

Dla odniesienia podczas pracy nad projektami w Go, posiadanie kompleksowego arkusza wskazówek Go w rękach może przyspieszyć rozwój i służyć jako szybki odniesienie do składni i typowych wzorców.

Gotowy do budowania swojego pierwszego API w Go? Zacznij od tych kroków:

  1. ✅ Ustaw środowisko Go i strukturę projektu
  2. ✅ Wybierz między biblioteką standardową a frameworkiem
  3. ✅ Zaimplementuj podstawowe punkty końcowe CRUD
  4. ✅ Dodaj walidację żądań i obsługa błędów
  5. ✅ Zaimplementuj middleware autoryzacji
  6. ✅ Dodaj integrację z bazą danych z pulą połączeń
  7. ✅ Napisz testy jednostkowe i integracyjne
  8. ✅ Dodaj dokumentację API
  9. ✅ Zaimplementuj logowanie i metryki
  10. ✅ Konteneryzuj z użyciem Docker
  11. ✅ Ustaw pipeline CI/CD
  12. ✅ Wdróż do produkcji z monitorowaniem

Podsumowanie

Język Go oferuje doskonałą podstawę do tworzenia interfejsów API typu REST, łącząc wydajność, prostotę oraz solidne narzędzia. Niezależnie od tego, czy tworzysz mikroserwisy, narzędzia wewnętrzne czy publiczne API, ekosystem Go ma dojrzałe rozwiązania na każde potrzeby.

Kluczem do sukcesu jest rozpoczęcie od solidnych wzorców architektonicznych, implementacja odpowiedniego obsługi błędów i walidacji od samego początku oraz budowanie kompleksowego pokrycia testów. W miarę rozwoju API, cechy wydajnościowe i silna obsługa współbieżności Go będą Cię wspierać.

Pamiętaj, że rozwój API jest iteracyjny. Zacznij od minimalnej realizacji, zbieraj opinie i doskonal odpowiedź na podstawie rzeczywistych wzorców użycia. Szybkie kompilowanie i proste refaktoryzowanie w Go sprawią, że ten cykl iteracyjny będzie płynny i produktywny.

Przydatne linki

Zewnętrzne zasoby

Oficjalna dokumentacja

Popularne frameworki i biblioteki

  • Framework Gin - Szybki framework HTTP z szerokim zakresem funkcji
  • Chi Router - Lekkie, idiomiczne routery do tworzenia usług HTTP w Go
  • Framework Echo - Wysokiej wydajności, rozszerzalny, minimalistyczny framework webowy
  • Framework Fiber - Framework webowy inspirowany Express, oparty na Fasthttp
  • GORM - Fantastyczna biblioteka ORM dla Go
  • golang-jwt - Implementacja JWT dla Go

Narzędzia do testowania i rozwoju

  • Testify - Narzędzia z częstymi asercjami i mockami
  • Pakiet httptest - Narzędzia standardowej biblioteki do testowania HTTP
  • Swaggo - Automatyczne generowanie dokumentacji API RESTful
  • Air - Live reload dla aplikacji Go podczas rozwoju

Praktyki i wytyczne

Bezpieczeństwo i uwierzytelnianie

Wydajność i monitorowanie

  • pprof - Wbudowane narzędzie profilowania dla programów Go
  • Klient Prometheus - Biblioteka do monitorowania dla Go
  • Zap Logger - Szybki, strukturalny, poziomowy logowanie