Token导航 LogoToken导航TokenDH.com
开发需要联网github未标认证来源可访问clear审计异常

golang-http-frameworksGo http frameworks 命令行

Agent Skill

golang-http-frameworks 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中需要围绕仓库状态、代码变更或协作事项进行整理时使用。可结合来源仓库、安装命令和原始 README 继续核验具体用法。安装前建议确认权限范围、维护状态,以及是否会触发联网、命令执行或文件读写。

总安装

5,655

周安装

231

GitHub Stars

40

下载量

1,811
CodexClaudeCursorGemini CLI

安装说明

本站只整理中文说明和来源信息,不托管安装包,也不代用户安装。

GitHub

来源数

3

许可证

MIT

最后核验

2026-05-01

来源状态

来源可访问

安装方式

通过对话安装

复制提示词发给支持本地命令或 Skills 的 AI 助手,先确认命令和权限,再让它执行。

请帮我安装这个 Agent Skill:golang-http-frameworks(Go http frameworks 命令行)
来源仓库:https://github.com/bobmatnyc/claude-mpm-skills
仓库路径:skills/golang-http-frameworks
安装命令:
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill golang-http-frameworks
安装前请先检查当前环境是否支持对应 CLI,并向我确认将要执行的命令、安装目录、联网范围和文件读写权限;确认后再执行。

命令行安装

复制命令到本机终端执行。不同来源提供的安装方式可能略有差异;本站展示可直接复制的安装命令,安装前请核对来源页面。

skills.shnpx skills
npx skills add https://github.com/bobmatnyc/claude-mpm-skills --skill golang-http-frameworks

简介

golang-http-frameworks 用于处理 GitHub 仓库、Issue、Pull Request 和代码协作信息,适合在 Codex、Claude、Cursor、Gemini CLI 中整理相关事项。

  • 适用于围绕仓库状态、代码变更或协作事项进行信息整理和分析的场景。
  • 通过 npx skills add 命令从指定 GitHub 仓库安装并使用该技能。
  • 安装前需确认权限范围、维护状态,以及是否会触发联网或文件读写操作。
  • 适用宿主包括 Codex、Claude、Cursor、Gemini CLI,接入前应确认版本、权限和运行环境要求。

SKILL.md

Go HTTP Frameworks & REST APIs

Overview

Go provides exceptional HTTP capabilities starting with the standard library's net/http package. Go 1.22+ introduced enhanced pattern routing in ServeMux, making stdlib viable for many applications. For more complex needs, frameworks like Chi, Gin, Echo, and Fiber offer additional features while maintaining Go's simplicity and performance.

Key Features:

  • 🌐 net/http: Production-ready standard library with Go 1.22+ routing
  • 🎯 Chi: Lightweight, stdlib-compatible router with middleware chains
  • Gin: High-performance framework with binding and validation
  • 🛡️ Echo: Type-safe, enterprise framework with OpenAPI support
  • 🚀 Fiber: Express.js-inspired framework with WebSocket support
  • 🔧 Middleware: Composable request/response processing
  • Validation: Struct tag-based request validation
  • 🧪 Testing: httptest.Server for comprehensive integration tests

When to Use This Skill

Activate this skill when:

  • Building RESTful APIs or web services
  • Choosing appropriate HTTP framework for project requirements
  • Implementing authentication or authorization middleware
  • Designing REST endpoint patterns and validation
  • Testing HTTP handlers and middleware chains
  • Optimizing API performance and response times
  • Migrating between HTTP frameworks

Framework Selection Guide

net/http (Standard Library) - Go 1.22+

Use When:

  • Building simple to moderate complexity APIs
  • Avoiding external dependencies is priority
  • Need maximum compatibility and long-term stability
  • Team prefers explicit over implicit patterns

Strengths:

  • Zero dependencies, part of Go standard library
  • Go 1.22+ pattern routing with path parameters
  • Excellent performance and stability
  • Extensive ecosystem compatibility
  • No framework lock-in

Limitations:

  • More verbose middleware composition
  • Manual request validation
  • No built-in binding or rendering

Example:

package main

import (
    "encoding/json"
    "net/http"
    "log"
)

// Go 1.22+ pattern routing
func main() {
    mux := http.NewServeMux()

    // Path parameters with {param} syntax
    mux.HandleFunc("GET /users/{id}", getUserHandler)
    mux.HandleFunc("POST /users", createUserHandler)
    mux.HandleFunc("GET /users", listUsersHandler)

    // Middleware wrapping
    handler := loggingMiddleware(mux)

    log.Fatal(http.ListenAndServe(":8080", handler))
}

func getUserHandler(w http.ResponseWriter, r *http.Request) {
    id := r.PathValue("id") // Go 1.22+ path parameter extraction

    user := User{ID: id, Name: "John Doe"}

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(user)
}

func loggingMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        log.Printf("%s %s", r.Method, r.URL.Path)
        next.ServeHTTP(w, r)
    })
}

type User struct {
    ID   string `json:"id"`
    Name string `json:"name"`
}

Chi - Lightweight Router

Use When:

  • Want stdlib-compatible router with better ergonomics
  • Need clean middleware composition
  • Prefer explicit over magic patterns
  • Building moderate to complex routing structures

Strengths:

  • 100% compatible with net/http
  • Excellent middleware ecosystem
  • Route grouping and nesting
  • Context-based parameter passing
  • Minimal performance overhead

Installation:

go get -u github.com/go-chi/chi/v5

Example:

package main

import (
    "encoding/json"
    "net/http"
    "github.com/go-chi/chi/v5"
    "github.com/go-chi/chi/v5/middleware"
)

func main() {
    r := chi.NewRouter()

    // Built-in middleware
    r.Use(middleware.Logger)
    r.Use(middleware.Recoverer)
    r.Use(middleware.RequestID)

    // Route grouping
    r.Route("/api/v1", func(r chi.Router) {
        r.Route("/users", func(r chi.Router) {
            r.Get("/", listUsers)
            r.Post("/", createUser)

            r.Route("/{userID}", func(r chi.Router) {
                r.Use(UserContext) // Middleware for nested routes
                r.Get("/", getUser)
                r.Put("/", updateUser)
                r.Delete("/", deleteUser)
            })
        })
    })

    http.ListenAndServe(":8080", r)
}

func UserContext(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        userID := chi.URLParam(r, "userID")
        // Load user from database, set in context
        ctx := context.WithValue(r.Context(), "user", userID)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

func getUser(w http.ResponseWriter, r *http.Request) {
    userID := r.Context().Value("user").(string)
    // Return user data
    json.NewEncoder(w).Encode(map[string]string{"id": userID})
}

Gin - High Performance Framework

Use When:

  • Need maximum performance (8x faster than most frameworks)
  • Want batteries-included experience
  • Require built-in validation and binding
  • Building JSON APIs with minimal boilerplate

Strengths:

  • Extremely fast (fastest Go framework in benchmarks)
  • Built-in JSON binding and validation
  • Middleware ecosystem
  • Group-based routing
  • Custom error handling

Installation:

go get -u github.com/gin-gonic/gin

Example:

package main

import (
    "net/http"
    "github.com/gin-gonic/gin"
)

type CreateUserRequest struct {
    Name  string `json:"name" binding:"required,min=3"`
    Email string `json:"email" binding:"required,email"`
    Age   int    `json:"age" binding:"required,gte=18"`
}

func main() {
    r := gin.Default() // Logger + Recovery middleware

    api := r.Group("/api/v1")
    {
        users := api.Group("/users")
        {
            users.GET("", listUsers)
            users.POST("", createUser)
            users.GET("/:id", getUser)
            users.PUT("/:id", updateUser)
            users.DELETE("/:id", deleteUser)
        }
    }

    r.Run(":8080")
}

func createUser(c *gin.Context) {
    var req CreateUserRequest

    // Automatic validation based on struct tags
    if err := c.ShouldBindJSON(&req); err != nil {
        c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    // Process user creation
    user := User{
        ID:    generateID(),
        Name:  req.Name,
        Email: req.Email,
        Age:   req.Age,
    }

    c.JSON(http.StatusCreated, user)
}

func getUser(c *gin.Context) {
    id := c.Param("id")

    // Return user
    c.JSON(http.StatusOK, gin.H{
        "id":   id,
        "name": "John Doe",
    })
}

Echo - Enterprise Framework

Use When:

  • Building enterprise applications
  • Need OpenAPI/Swagger integration
  • Want comprehensive middleware library
  • Require type-safe routing and binding

Strengths:

  • Type-safe routing with automatic parameter binding
  • Built-in middleware for common patterns
  • OpenAPI/Swagger generation support
  • Excellent error handling middleware
  • WebSocket support

Installation:

go get -u github.com/labstack/echo/v4

Example:

package main

import (
    "net/http"
    "github.com/labstack/echo/v4"
    "github.com/labstack/echo/v4/middleware"
)

func main() {
    e := echo.New()

    // Middleware
    e.Use(middleware.Logger())
    e.Use(middleware.Recover())
    e.Use(middleware.CORS())

    // Routes
    e.GET("/users/:id", getUser)
    e.POST("/users", createUser)
    e.PUT("/users/:id", updateUser)
    e.DELETE("/users/:id", deleteUser)

    e.Logger.Fatal(e.Start(":8080"))
}

func getUser(c echo.Context) error {
    id := c.Param("id")

    user := User{ID: id, Name: "John Doe"}
    return c.JSON(http.StatusOK, user)
}

func createUser(c echo.Context) error {
    var user User

    if err := c.Bind(&user); err != nil {
        return echo.NewHTTPError(http.StatusBadRequest, err.Error())
    }

    if err := c.Validate(&user); err != nil {
        return echo.NewHTTPError(http.StatusBadRequest, err.Error())
    }

    return c.JSON(http.StatusCreated, user)
}

// Custom error handler
func customErrorHandler(err error, c echo.Context) {
    code := http.StatusInternalServerError
    message := "Internal Server Error"

    if he, ok := err.(*echo.HTTPError); ok {
        code = he.Code
        message = he.Message.(string)
    }

    c.JSON(code, map[string]string{"error": message})
}

Fiber - Express.js Style

Use When:

  • Team familiar with Express.js patterns
  • Need WebSocket support out of the box
  • Building real-time applications
  • Want fastest route matching performance

Strengths:

  • Express.js-inspired API (easy for Node.js developers)
  • Fastest route matching (uses fasthttp)
  • Built-in WebSocket support
  • Template engine support
  • File upload handling

Limitations:

  • Uses fasthttp instead of net/http (less ecosystem compatibility)
  • Not compatible with standard http.Handler interface
  • Slightly less mature ecosystem

Installation:

go get -u github.com/gofiber/fiber/v2

Example:

package main

import (
    "github.com/gofiber/fiber/v2"
    "github.com/gofiber/fiber/v2/middleware/logger"
    "github.com/gofiber/fiber/v2/middleware/cors"
)

func main() {
    app := fiber.New()

    // Middleware
    app.Use(logger.New())
    app.Use(cors.New())

    // Routes
    api := app.Group("/api/v1")

    users := api.Group("/users")
    users.Get("/", listUsers)
    users.Post("/", createUser)
    users.Get("/:id", getUser)
    users.Put("/:id", updateUser)
    users.Delete("/:id", deleteUser)

    app.Listen(":8080")
}

func getUser(c *fiber.Ctx) error {
    id := c.Params("id")

    return c.JSON(fiber.Map{
        "id":   id,
        "name": "John Doe",
    })
}

func createUser(c *fiber.Ctx) error {
    var user User

    if err := c.BodyParser(&user); err != nil {
        return c.Status(400).JSON(fiber.Map{"error": err.Error()})
    }

    return c.Status(201).JSON(user)
}

Common HTTP Patterns

Request Validation

Struct Tag Validation:

import "github.com/go-playground/validator/v10"

type CreateUserRequest struct {
    Name     string `json:"name" validate:"required,min=3,max=50"`
    Email    string `json:"email" validate:"required,email"`
    Age      int    `json:"age" validate:"required,gte=18,lte=120"`
    Password string `json:"password" validate:"required,min=8"`
}

var validate = validator.New()

func validateRequest(req interface{}) error {
    return validate.Struct(req)
}

// Usage
func createUser(w http.ResponseWriter, r *http.Request) {
    var req CreateUserRequest

    if err := json.NewDecoder(r.Body).Decode(&req); err != nil {
        http.Error(w, "Invalid JSON", http.StatusBadRequest)
        return
    }

    if err := validateRequest(&req); err != nil {
        http.Error(w, err.Error(), http.StatusBadRequest)
        return
    }

    // Process valid request
}

Custom Validators:

import "github.com/go-playground/validator/v10"

var validate = validator.New()

func init() {
    validate.RegisterValidation("username", validateUsername)
}

func validateUsername(fl validator.FieldLevel) bool {
    username := fl.Field().String()
    // Custom validation logic
    return len(username) >= 3 && isAlphanumeric(username)
}

type SignupRequest struct {
    Username string `validate:"required,username"`
    Email    string `validate:"required,email"`
}

Middleware Patterns

Authentication Middleware:

func AuthMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        token := r.Header.Get("Authorization")

        if token == "" {
            http.Error(w, "Unauthorized", http.StatusUnauthorized)
            return
        }

        // Validate token
        userID, err := validateToken(token)
        if err != nil {
            http.Error(w, "Invalid token", http.StatusUnauthorized)
            return
        }

        // Add user to context
        ctx := context.WithValue(r.Context(), "userID", userID)
        next.ServeHTTP(w, r.WithContext(ctx))
    })
}

Rate Limiting Middleware:

import (
    "golang.org/x/time/rate"
    "sync"
)

type RateLimiter struct {
    limiters map[string]*rate.Limiter
    mu       sync.RWMutex
    rate     rate.Limit
    burst    int
}

func NewRateLimiter(r rate.Limit, b int) *RateLimiter {
    return &RateLimiter{
        limiters: make(map[string]*rate.Limiter),
        rate:     r,
        burst:    b,
    }
}

func (rl *RateLimiter) getLimiter(ip string) *rate.Limiter {
    rl.mu.Lock()
    defer rl.mu.Unlock()

    limiter, exists := rl.limiters[ip]
    if !exists {
        limiter = rate.NewLimiter(rl.rate, rl.burst)
        rl.limiters[ip] = limiter
    }

    return limiter
}

func (rl *RateLimiter) Middleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        ip := r.RemoteAddr
        limiter := rl.getLimiter(ip)

        if !limiter.Allow() {
            http.Error(w, "Rate limit exceeded", http.StatusTooManyRequests)
            return
        }

        next.ServeHTTP(w, r)
    })
}

CORS Middleware:

func CORSMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Set("Access-Control-Allow-Origin", "*")
        w.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
        w.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")

        if r.Method == "OPTIONS" {
            w.WriteHeader(http.StatusOK)
            return
        }

        next.ServeHTTP(w, r)
    })
}

Error Handling Strategies

Custom Error Types:

type APIError struct {
    Code    int    `json:"code"`
    Message string `json:"message"`
    Details string `json:"details,omitempty"`
}

func (e *APIError) Error() string {
    return e.Message
}

// Error constructors
func NewBadRequestError(msg string) *APIError {
    return &APIError{Code: http.StatusBadRequest, Message: msg}
}

func NewNotFoundError(msg string) *APIError {
    return &APIError{Code: http.StatusNotFound, Message: msg}
}

func NewInternalError(msg string) *APIError {
    return &APIError{Code: http.StatusInternalServerError, Message: msg}
}

Error Response Middleware:

type APIHandler func(w http.ResponseWriter, r *http.Request) error

func ErrorHandlerMiddleware(h APIHandler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        err := h(w, r)
        if err == nil {
            return
        }

        // Handle different error types
        var apiErr *APIError
        if errors.As(err, &apiErr) {
            w.Header().Set("Content-Type", "application/json")
            w.WriteHeader(apiErr.Code)
            json.NewEncoder(w).Encode(apiErr)
            return
        }

        // Unknown error - log and return generic message
        log.Printf("Internal error: %v", err)
        w.WriteHeader(http.StatusInternalServerError)
        json.NewEncoder(w).Encode(APIError{
            Code:    http.StatusInternalServerError,
            Message: "Internal server error",
        })
    })
}

// Usage
func getUserHandler(w http.ResponseWriter, r *http.Request) error {
    id := r.PathValue("id")

    user, err := db.GetUser(id)
    if err != nil {
        if errors.Is(err, sql.ErrNoRows) {
            return NewNotFoundError("User not found")
        }
        return fmt.Errorf("database error: %w", err)
    }

    w.Header().Set("Content-Type", "application/json")
    return json.NewEncoder(w).Encode(user)
}

// Register with middleware
mux.Handle("GET /users/{id}", ErrorHandlerMiddleware(getUserHandler))

REST API Design Patterns

Resource Naming Conventions:

// Good: Plural nouns for collections
GET    /api/v1/users           // List users
POST   /api/v1/users           // Create user
GET    /api/v1/users/{id}      // Get user
PUT    /api/v1/users/{id}      // Update user (full)
PATCH  /api/v1/users/{id}      // Update user (partial)
DELETE /api/v1/users/{id}      // Delete user

// Nested resources
GET    /api/v1/users/{id}/posts        // User's posts
POST   /api/v1/users/{id}/posts        // Create post for user
GET    /api/v1/users/{id}/posts/{pid}  // Specific post

// Avoid: Verbs in URLs (use HTTP methods instead)
// Bad: POST /api/v1/users/create
// Bad: GET  /api/v1/users/get/{id}

Pagination Pattern:

type PaginationParams struct {
    Page     int `json:"page" validate:"gte=1"`
    PageSize int `json:"page_size" validate:"gte=1,lte=100"`
}

type PaginatedResponse struct {
    Data       interface{} `json:"data"`
    Page       int         `json:"page"`
    PageSize   int         `json:"page_size"`
    TotalCount int         `json:"total_count"`
    TotalPages int         `json:"total_pages"`
}

func listUsers(w http.ResponseWriter, r *http.Request) {
    // Parse pagination params
    page, _ := strconv.Atoi(r.URL.Query().Get("page"))
    if page < 1 {
        page = 1
    }

    pageSize, _ := strconv.Atoi(r.URL.Query().Get("page_size"))
    if pageSize < 1 || pageSize > 100 {
        pageSize = 20
    }

    // Fetch data
    users, totalCount := db.GetUsers(page, pageSize)
    totalPages := (totalCount + pageSize - 1) / pageSize

    response := PaginatedResponse{
        Data:       users,
        Page:       page,
        PageSize:   pageSize,
        TotalCount: totalCount,
        TotalPages: totalPages,
    }

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(response)
}

Query Parameter Filtering:

type UserFilter struct {
    Status    string `json:"status"`
    Role      string `json:"role"`
    CreatedAt string `json:"created_at"`
    Search    string `json:"search"`
}

func parseFilters(r *http.Request) UserFilter {
    return UserFilter{
        Status:    r.URL.Query().Get("status"),
        Role:      r.URL.Query().Get("role"),
        CreatedAt: r.URL.Query().Get("created_at"),
        Search:    r.URL.Query().Get("search"),
    }
}

func listUsers(w http.ResponseWriter, r *http.Request) {
    filters := parseFilters(r)

    users := db.GetUsersWithFilters(filters)

    w.Header().Set("Content-Type", "application/json")
    json.NewEncoder(w).Encode(users)
}

// Example request: GET /api/v1/users?status=active&role=admin&search=john

HTTP Client Patterns

Production-Ready HTTP Client:

import (
    "context"
    "net/http"
    "time"
)

func NewHTTPClient() *http.Client {
    return &http.Client{
        Timeout: 30 * time.Second,
        Transport: &http.Transport{
            MaxIdleConns:        100,
            MaxIdleConnsPerHost: 10,
            IdleConnTimeout:     90 * time.Second,
            DisableKeepAlives:   false,
        },
    }
}

// Making requests with context
func fetchUser(ctx context.Context, userID string) (*User, error) {
    client := NewHTTPClient()

    req, err := http.NewRequestWithContext(
        ctx,
        "GET",
        fmt.Sprintf("https://api.example.com/users/%s", userID),
        nil,
    )
    if err != nil {
        return nil, fmt.Errorf("create request: %w", err)
    }

    req.Header.Set("Accept", "application/json")
    req.Header.Set("Authorization", "Bearer "+getToken())

    resp, err := client.Do(req)
    if err != nil {
        return nil, fmt.Errorf("execute request: %w", err)
    }
    defer resp.Body.Close()

    if resp.StatusCode != http.StatusOK {
        return nil, fmt.Errorf("unexpected status: %d", resp.StatusCode)
    }

    var user User
    if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
        return nil, fmt.Errorf("decode response: %w", err)
    }

    return &user, nil
}

Retry Logic with Exponential Backoff:

import (
    "context"
    "math"
    "time"
)

type RetryConfig struct {
    MaxRetries int
    BaseDelay  time.Duration
    MaxDelay   time.Duration
}

func DoWithRetry(ctx context.Context, cfg RetryConfig, fn func() error) error {
    var err error

    for attempt := 0; attempt <= cfg.MaxRetries; attempt++ {
        err = fn()
        if err == nil {
            return nil
        }

        if attempt < cfg.MaxRetries {
            // Exponential backoff
            delay := time.Duration(math.Pow(2, float64(attempt))) * cfg.BaseDelay
            if delay > cfg.MaxDelay {
                delay = cfg.MaxDelay
            }

            select {
            case <-ctx.Done():
                return ctx.Err()
            case <-time.After(delay):
                // Continue to next attempt
            }
        }
    }

    return fmt.Errorf("max retries exceeded: %w", err)
}

// Usage
err := DoWithRetry(ctx, RetryConfig{
    MaxRetries: 3,
    BaseDelay:  100 * time.Millisecond,
    MaxDelay:   2 * time.Second,
}, func() error {
    return makeAPIRequest()
})

Testing HTTP Handlers

Using httptest.Server:

import (
    "net/http"
    "net/http/httptest"
    "testing"
)

func TestGetUser(t *testing.T) {
    // Create test server
    ts := httptest.NewServer(http.HandlerFunc(getUserHandler))
    defer ts.Close()

    // Make request
    resp, err := http.Get(ts.URL + "/users/123")
    if err != nil {
        t.Fatal(err)
    }
    defer resp.Body.Close()

    // Assertions
    if resp.StatusCode != http.StatusOK {
        t.Errorf("expected status 200, got %d", resp.StatusCode)
    }

    var user User
    if err := json.NewDecoder(resp.Body).Decode(&user); err != nil {
        t.Fatal(err)
    }

    if user.ID != "123" {
        t.Errorf("expected user ID 123, got %s", user.ID)
    }
}

Testing Middleware:

func TestAuthMiddleware(t *testing.T) {
    handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        userID := r.Context().Value("userID")
        if userID == nil {
            t.Error("userID not found in context")
        }
        w.WriteHeader(http.StatusOK)
    })

    wrapped := AuthMiddleware(handler)

    tests := []struct {
        name       string
        token      string
        wantStatus int
    }{
        {"Valid token", "valid-token-123", http.StatusOK},
        {"Missing token", "", http.StatusUnauthorized},
        {"Invalid token", "invalid", http.StatusUnauthorized},
    }

    for _, tt := range tests {
        t.Run(tt.name, func(t *testing.T) {
            req := httptest.NewRequest("GET", "/test", nil)
            if tt.token != "" {
                req.Header.Set("Authorization", tt.token)
            }

            rr := httptest.NewRecorder()
            wrapped.ServeHTTP(rr, req)

            if rr.Code != tt.wantStatus {
                t.Errorf("expected status %d, got %d", tt.wantStatus, rr.Code)
            }
        })
    }
}

Performance Optimization

Response Compression:

import (
    "compress/gzip"
    "io"
    "net/http"
    "strings"
)

type gzipResponseWriter struct {
    io.Writer
    http.ResponseWriter
}

func (w gzipResponseWriter) Write(b []byte) (int, error) {
    return w.Writer.Write(b)
}

func GzipMiddleware(next http.Handler) http.Handler {
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
        if !strings.Contains(r.Header.Get("Accept-Encoding"), "gzip") {
            next.ServeHTTP(w, r)
            return
        }

        w.Header().Set("Content-Encoding", "gzip")
        gz := gzip.NewWriter(w)
        defer gz.Close()

        gzw := gzipResponseWriter{Writer: gz, ResponseWriter: w}
        next.ServeHTTP(gzw, r)
    })
}

Connection Pooling Configuration:

import (
    "net"
    "net/http"
    "time"
)

func NewProductionHTTPClient() *http.Client {
    return &http.Client{
        Timeout: 30 * time.Second,
        Transport: &http.Transport{
            Proxy: http.ProxyFromEnvironment,
            DialContext: (&net.Dialer{
                Timeout:   30 * time.Second,
                KeepAlive: 30 * time.Second,
            }).DialContext,
            ForceAttemptHTTP2:     true,
            MaxIdleConns:          100,
            MaxIdleConnsPerHost:   10,
            IdleConnTimeout:       90 * time.Second,
            TLSHandshakeTimeout:   10 * time.Second,
            ExpectContinueTimeout: 1 * time.Second,
        },
    }
}

Decision Tree

Building HTTP API in Go?
│
├─ Simple API, few dependencies? → net/http (stdlib)
│  ├─ Go 1.22+? → Use new ServeMux pattern routing
│  └─ Go < 1.22? → Consider Chi for better routing
│
├─ Need stdlib compatibility + better ergonomics? → Chi
│  └─ Great for: Middleware chains, route grouping
│
├─ Maximum performance priority? → Gin
│  └─ Great for: JSON APIs, high throughput services
│
├─ Enterprise app with OpenAPI? → Echo
│  └─ Great for: Type safety, comprehensive middleware
│
└─ Team knows Express.js + need WebSockets? → Fiber
   └─ Note: Uses fasthttp, not stdlib-compatible

Common Pitfalls

Pitfall 1: Not Closing Response Bodies

// Bad: Memory leak
resp, _ := http.Get(url)
body, _ := io.ReadAll(resp.Body) // Never closed!

// Good: Always defer close
resp, err := http.Get(url)
if err != nil {
    return err
}
defer resp.Body.Close()
body, err := io.ReadAll(resp.Body)

Pitfall 2: Not Using Context for Timeouts

// Bad: No timeout control
resp, _ := http.Get(url)

// Good: Use context with timeout
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()

req, _ := http.NewRequestWithContext(ctx, "GET", url, nil)
resp, err := client.Do(req)

Pitfall 3: Ignoring HTTP Status Codes

// Bad: Not checking status
resp, _ := http.Get(url)
defer resp.Body.Close()
json.NewDecoder(resp.Body).Decode(&result)

// Good: Always check status
resp, err := http.Get(url)
if err != nil {
    return err
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
    return fmt.Errorf("unexpected status: %d", resp.StatusCode)
}

Pitfall 4: Not Reusing HTTP Clients

// Bad: Creates new client per request (no connection pooling)
func makeRequest() {
    client := &http.Client{}
    resp, _ := client.Get(url)
}

// Good: Reuse client for connection pooling
var httpClient = &http.Client{
    Timeout: 30 * time.Second,
}

func makeRequest() {
    resp, _ := httpClient.Get(url)
}

Related Skills

  • golang-testing-strategies: Testing HTTP handlers and middleware
  • golang-database-patterns: Integrating databases with HTTP APIs
  • toolchains-typescript-frameworks-nodejs-backend: Comparison with Node.js patterns

References

适合场景

01

用户想查找某类 Agent Skill 时

02

需要根据任务场景推荐可安装能力包时

03

需要对比不同来源的安装命令和来源信息时

04

需要参考平台分布和安装热度时

能力概览

能力 1

按任务关键词查找相关 Skills

能力 2

展示可复制的安装命令

能力 3

保留来源站点、仓库和原始说明,方便继续核验

能力 4

补充不同宿主或平台的使用分布数据

能力 5

展示第三方安全扫描或审计结果

安装后应在对应宿主中按原始 README 的触发条件使用;具体调用方式请以来源页面和 README 为准。

平台分布

Claude Code

31.16%
按下载量换算564

OpenCode

24.05%
按下载量换算436

Gemini CLI

15.22%
按下载量换算276

Antigravity

12.89%
按下载量换算233

github-copilot

7.78%
按下载量换算141

windsurf

3%
按下载量换算54

安全审计

Gen Agent Trust Hub

未通过

Socket

通过

Snyk

通过

权限和风险

需要联网

该 Skill 可能需要联网访问来源站点、仓库或外部 API;具体网络访问范围需要结合源码和 README 复核。

安装前确认

本站仅展示第三方公开信息,不托管安装包,不提供自动安装或运行环境。安装前应自行审查源码、依赖和命令行为。来源安全扫描存在 warning/failed 结果,不能写成本站确认安全。

来源信息

继续浏览同类 Skills