Tworzenie interfejsów REST API w Go: Kompletny przewodnik
Tworzenie gotowych do produkcji interfejsów REST API z wykorzystaniem rozbudowanego ekosystemu Go
Tworzenie wydajnych REST API w Go stało się standardowym podejściem do napędzania systemów w firmach takich jak Google, Uber, Dropbox oraz w nieustającej liczbie startupów.
Prostota Go, silne wsparcie dla współbieżności oraz szybka kompilacja czynią go idealnym wyborem dla mikroserwisów i rozwoju backendu.
To wspaniałe obrazek został wygenerowany przez FLUX.1-Kontext-dev: Model AI do augmentacji obrazów.
Dlaczego Go do tworzenia API?
Go wnosi kilka przekonujących zalet do rozwoju API:
Wydajność i efektywność: Go kompiluje się do natywnego kodu maszynowego, oferując wydajność bliską C bez jej złożoności. Efektywna zarządzanie pamięcią i małe rozmiary plików binarnych czynią go doskonałym do wdrożeń w kontenerach.
Wbudowana współbieżność: Gorutyny i kanały sprawiają, że obsługa tysięcy równoczesnych żądań jest prosta. Możesz przetwarzać wiele wywołań API jednocześnie bez skomplikowanego kodu wątków.
Silna biblioteka standardowa: Pakiet net/http dostarcza gotowy do produkcji serwer HTTP od razu po instalacji. Możesz budować kompletne API bez żadnych zewnętrznych zależności.
Szybka kompilacja: Szybkość kompilacji Go umożliwia szybką iterację podczas rozwoju. Duże projekty kompilują się w sekundy, a nie minuty.
Statyczna typowość z prostotą: System typów Go wykrywa błędy w czasie kompilacji, jednocześnie zachowując klarowność kodu. Język ma mały zestaw funkcji, który jest szybki do nauki.
Podejścia do budowania API w Go
Używanie biblioteki standardowej
Biblioteka standardowa Go dostarcza wszystkiego, czego potrzebujesz do podstawowego rozwoju API. Oto minimalny przykład:
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))
}
To podejście oferuje pełną kontrolę i zero zależności. Jest idealne dla prostych API lub gdy chcesz zrozumieć obsługę HTTP na fundamentalnym poziomie.
Popularne frameworki webowe w Go
Podczas gdy biblioteka standardowa jest potężna, frameworki mogą przyspieszyć rozwój:
Gin: Najpopularniejszy framework webowy w Go, znany ze swojej wydajności i łatwości użycia. Dostarcza wygodne routowanie, wsparcie dla middleware oraz 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, idiomatic router, który czuje się jak rozszerzenie biblioteki standardowej. Jest szczególnie dobry do budowania usług RESTful z zagnieżdżonym routowaniem.
Echo: Framework o wysokiej wydajności z rozszerzonym middleware i doskonałą dokumentacją. Jest zoptymalizowany pod kątem szybkości, pozostając przyjaznym dla deweloperów.
Fiber: Zainspirowany przez Express.js, zbudowany na Fasthttp. Jest najszybszą opcją, ale używa innej implementacji HTTP niż biblioteka standardowa.
Wzorce architektoniczne
Podczas pracy z operacjami na bazie danych w Go, musisz rozważyć swoją strategię ORM. Różne projekty porównały podejścia takie jak GORM, Ent, Bun i sqlc, każda oferująca różne kompromisy między produktywnością dewelopera a wydajnością.
Architektura warstwowa
Strukturyzuj swoje API z wyraźnym rozdzieleniem odpowiedzialności:
// Warstwa Handler - aspekty 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 Service - 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 Repository - 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 rozdzielenie ułatwia testowanie i utrzymuje kod w stanie zdatnym do utrzymania wraz ze wzrostem projektu.
Domain-Driven Design
Dla skomplikowanych aplikacji, rozważ organizację kodu według domen zamiast warstw technicznych. Każda paczka domeny zawiera swoje własne modele, usługi i repozytoria.
Jeśli budujesz aplikacje wielodostępne (multi-tenant), zrozumienie wzorców baz danych dla wielodostępności staje się kluczowe dla architektury Twojego API.
Obsługa żądań i walidacja
Walidacja wejściowa
Zawsze waliduj przychodzące dane przed ich przetworzeniem:
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
}
// Przetwórz ważne żądanie
}
Pakiet go-playground/validator dostarcza rozszerzone reguły walidacji i niestandardowych walidatorów.
Kontekst żądania
Używaj kontekstu do wartości o zakresie żą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, "Unauthorized", http.StatusUnauthorized)
return
}
ctx := context.WithValue(r.Context(), "userID", userID)
next.ServeHTTP(w, r.WithContext(ctx))
})
}
Aby głęboko zrozumieć najlepsze praktyki dotyczące kontekstu — w tym typowane klucze, propagację anulowania, budżety timeoutów i eleganckie wyłączanie — zobacz Go context.Context Done Right.
Autoryzacja i bezpieczeństwo
Autoryzacja oparta na JWT
JSON Web Tokens dostarczają 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
Implementuj przekrojowe aspekty jako 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 żądań/sek, burst 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)
})
}
Obsługa błędów
Implementuj spójne odpowiedzi błędów:
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",
}
// Zaloguj rzeczywisty błąd do debugowania
log.Printf("Unexpected error: %v", err)
}
w.Header().Set("Content-Type", "application/json")
w.WriteHeader(apiErr.Code)
json.NewEncoder(w).Encode(apiErr)
}
Aby uzyskać głębsze spojrzenie na architekturę obsługi błędów przez warstwy repozytorium, usługi i handlerów — w tym błędy sentryczne, niestandardowe typy błędów, tłumaczenie granic i mapowanie bezpiecznych odpowiedzi — zobacz Go Error Handling Architecture: Boundaries and Patterns.
Integracja z bazą danych
Zarządzanie połączeniami
Używaj puli połączeń dla efektywnego 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 handlery HTTP używając 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)
}
Testy integracyjne
Testuj kompletne przepływy z testową bazą danych:
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)
}
Dokumentacja API
OpenAPI/Swagger
Dokumentuj swoje API używając specyfikacji OpenAPI:
// @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
}
Używaj swaggo/swag do generowania interaktywnej dokumentacji API z tych komentarzy.
Optymalizacja wydajności
Kompresja odpowiedzi
Włącz kompresję gzip dla odpowiedzi:
import "github.com/NYTimes/gziphandler"
func main() {
r := chi.NewRouter()
r.Use(gziphandler.GzipHandler)
// Rest of setup
}
Buforowanie (Caching)
Implementuj buforowanie dla często dostępnych 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) {
// 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
}
Pula połączeń
Ponownie używaj połączeń HTTP dla zewnętrznych wywołań API:
var httpClient = &http.Client{
Timeout: 10 * time.Second,
Transport: &http.Transport{
MaxIdleConns: 100,
MaxIdleConnsPerHost: 10,
IdleConnTimeout: 90 * time.Second,
},
}
Rozważania wdrożeniowe
Konteneryzacja Docker
Twórz efektywne obrazy Docker używając wieloetapowych buildów:
# 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"]
To produkuje minimalny obraz (typowo poniżej 20MB) z tylko Twoim binarnym plikiem 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
}
Elegantne wyłączanie
Obsługuj sygnały wyłączania poprawnie:
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")
}
Monitorowanie i obserwowalność
Logowanie strukturalne
Używaj strukturalnego logowania dla lepszej możliwości wyszukiwania:
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 jest solidnym wyborem, gdy chcesz dojrzałego loggera z trzeciej strony. Jeśli wolisz bibliotekę standardową, log/slog (Go 1.21+) dostarcza przyjazne dla JSON rekordy, redakcję na poziomie handlera i pola, które korelują ze śladami i potokami logów. Zobacz Structured Logging in Go with slog for Observability and Alerting.
Zbieranie metryk
Eksponuj metryki Prometheus:
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)
})
}
Zaawansowane wzorce
Praca ze strukturalnym wyjściem
Podczas budowania API integrujących się z LLM, możesz potrzebować ograniczać odpowiedzi ze strukturalnym wyjściem. Jest to szczególnie użyteczne dla funkcji zasilanych AI w Twoim API.
Scraping webowy dla źródeł danych API
Jeśli Twoje API musi agregować dane z innych stron internetowych, zrozumienie alternatyw dla Beautiful Soup w Go może pomóc Ci zaimplementować solidną funkcjonalność scrapingu webowego.
Generowanie dokumentów
Wiele API potrzebuje generować dokumenty. Dla generowania PDF w Go, istnieje kilka bibliotek i podejść, które możesz zintegrować z końcówkami swojego API.
Wyszukiwanie semantyczne i reranking
Dla API zajmujących się wyszukiwaniem tekstowym i odzyskiwaniem, implementacja rerankingu z modelami embeddingowymi może znacząco poprawić istotność wyników wyszukiwania.
Budowanie serwerów MCP
Jeśli implementujesz API zgodne z Modelem Kontekstowym (MCP), sprawdź ten przewodnik implementacji serwerów MCP w Go, który obejmuje specyfikacje protokołu i praktyczne implementacje.
Częste pułapki i rozwiązania
Nieprawidłowe użycie kontekstów
Zawsze przekazuj i szanuj kontekst przez cały łańcuch wywołań. To umożliwia poprawną obsługę anulowania i timeoutów.
Ignorowanie wycieków gorutin
Upewnij się, że wszystkie gorutyny mogą się zakończyć. Używaj kontekstów z terminami i zawsze miej sposób na sygnalizację zakończenia.
Słaba obsługa błędów
Nie zwracaj surowych błędów bazy danych klientom. Obejmuj błędy kontekstem i zwracaj zsanitaryzowane wiadomości w odpowiedziach API.
Brak walidacji wejściowej
Waliduj wszystkie wejścia na punkcie wejścia. Nigdy nie ufaj danym klienta, nawet od zautoryzowanych użytkowników.
Niewystarczające testowanie
Nie testuj tylko szczęśliwego przypadku. Pokrywaj przypadki błędów, warunki brzegowe i scenariusze współbieżnego dostępu.
Podsumowanie najlepszych praktyk
-
Zacznij od prostego: Zacznij od biblioteki standardowej. Dodaj frameworki, gdy złożoność tego wymaga.
-
Warstwuj swoją aplikację: Rozdziel handlery HTTP, logikę biznesową i dostęp do danych dla utrzymalności.
-
Waliduj wszystko: Sprawdzaj wejścia na granicach. Używaj silnego typowania i bibliotek walidacji.
-
Obsługuj błędy spójnie: Zwracaj strukturalne odpowiedzi błędów. Loguj wewnętrzne błędy, ale nie eksponuj ich.
-
Używaj Middleware: Implementuj przekrojowe aspekty (autoryzacja, logowanie, metryki) jako middleware.
-
Testuj dokładnie: Pisuj testy jednostkowe dla logiki, testy integracyjne dla dostępu do danych i testy end-to-end dla przepływów.
-
Dokumentuj swoje API: Używaj OpenAPI/Swagger dla interaktywnej dokumentacji.
-
Monitoruj produkcję: Implementuj strukturalne logowanie, zbieranie metryk i checki zdrowotności.
-
Optymizuj ostrożnie: Profiluj przed optymalizacją. Używaj buforowania, puli połączeń i kompresji tam, gdzie jest to korzystne.
-
Projektuj dla eleganckiego wyłączania: Obsługuj sygnały terminacji i opróżniaj połączenia poprawnie.
Checklista rozpoczęcia
Dla odniesienia przy pracy nad projektami Go, posiadanie kompletnego cheatsheta Go pod ręką może przyspieszyć rozwój i służyć jako szybkie odniesienie dla składni i powszechnych wzorców.
Gotowy na budowanie swojego pierwszego API w Go? Zacznij od tych kroków:
- ✅ Skonfiguruj swoje środowisko Go i strukturę projektu
- ✅ Wybierz między biblioteką standardową a frameworkiem
- ✅ Zaimplementuj podstawowe końcówki CRUD
- ✅ Dodaj walidację żądań i obsługę błędów
- ✅ Zaimplementuj middleware autoryzacji
- ✅ Dodaj integrację z bazą danych z pulą połączeń
- ✅ Napisz testy jednostkowe i integracyjne
- ✅ Dodaj dokumentację API
- ✅ Zaimplementuj logowanie i metryki
- ✅ Skonteneryzuj z Dockerem
- ✅ Skonfiguruj pipeline CI/CD
- ✅ Wdroż na produkcję z monitorowaniem
Podsumowanie
Go dostarcza doskonałą podstawę do budowania REST API, łącząc wydajność, prostotę i solidne narzędzia. Niezależnie od tego, czy budujesz mikroserwisy, narzędzia wewnętrzne, czy publiczne API, ekosystem Go ma dojrzałe rozwiązania dla każdej potrzeby.
Kluczem do sukcesu jest rozpoczęcie od solidnych wzorców architektonicznych, implementacja poprawnej obsługi błędów i walidacji od początku oraz budowa kompleksowego pokrycia testowego. W miarę rozwoju Twojego API, charakterystyka wydajności Go i silne wsparcie dla współbieżności będą Ci dobrze służyć.
Pamiętaj, że rozwój API jest iteracyjny. Zacznij od minimalnej wykonalnej implementacji, zbierz feedback i udoskonál swoje podejście na podstawie rzeczywistych wzorców użycia. Szybka kompilacja Go i proste refaktoryzowanie czynią ten cykl iteracji płynnym i produktywnym.
Przydatne linki
- 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
Zasoby zewnętrzne
Oficjalna dokumentacja
- Go Official Documentation - Oficjalna dokumentacja Go i tutoriale
- Go net/http Package - Dokumentacja pakietu HTTP z biblioteki standardowej
- Effective Go - Najlepsze praktyki dla pisania czytelnego, idiomaticznego kodu Go
Popularne frameworki i biblioteki
- Gin Web Framework - Szybki framework webowy HTTP z rozszerzonymi funkcjami
- Chi Router - Lekki, idiomatic router do budowania usług HTTP w Go
- Echo Framework - Wysokowydajny, rozszerzalny, minimalistyczny framework webowy
- Fiber Framework - Framework webowy zainspirowany przez Express, zbudowany na Fasthttp
- GORM - Fantastyczna biblioteka ORM dla Golang
- golang-jwt - Implementacja JWT dla Go
Narzędzia testowe i deweloperskie
- Testify - Zestaw narzędzi ze wspólnymi asercjami i mockami
- httptest Package - Narzędzia z biblioteki standardowej do testowania HTTP
- Swaggo - Automatyczne generowanie dokumentacji RESTful API
- Air - Live reload dla aplikacji Go podczas rozwoju
Najlepsze praktyki i przewodniki
- Go Project Layout - Standardowe układy projektów Go
- Uber Go Style Guide - Kompletny przewodnik stylowy Go od Uber
- Go Code Review Comments - Powszechne komentarze podczas przeglądów kodu Go
- REST API Design Best Practices - Ogólne zasady projektowania REST API
Bezpieczeństwo i autoryzacja
- OWASP Go Secure Coding Practices - Wytyczne bezpieczeństwa dla aplikacji Go
- OAuth2 for Go - Implementacja OAuth 2.0
- bcrypt Package - Implementacja haszowania haseł
Wydajność i monitorowanie
- pprof - Wbudowane narzędzie profilujące dla programów Go
- Prometheus Client - Biblioteka instrumentacji Prometheus dla Go
- Zap Logger - Szybkie, strukturalne, poziomowe logowanie
- App Architecture hub — API design, code structure, and integration patterns