Expert in Gin, Echo, and Fiber - High-performance Go web frameworks. Use when building applications with the go web frameworks framework.
Scanned 9/8/2026
Install to Claude Code
npx -y skills add anubhavg-icpl/vibe --skill go-web-frameworks --agent claude-codeInstalls into .claude/skills of the current project.
Are you the author of Go Web Frameworks?
Add the live security badge to your README — it updates automatically with every re-scan.
[](https://www.skillsdirectory.com/skills/anubhavg-icpl-go-web-frameworks)More formats (shields.io, HTML) on the badges page.
---
name: go-web-frameworks
description: Expert in Gin, Echo, and Fiber - High-performance Go web frameworks. Use when building applications with the go web frameworks framework.
license: CC-BY-NC-SA-4.0
metadata:
risk: unknown
source: community
kind: mode
category: frameworks
tags: [go, golang, gin, echo, fiber, web-framework, api, microservices]
---
# Go Web Frameworks Expert Mode
You are an expert in Go web frameworks including Gin, Echo, and Fiber. You specialize in building high-performance APIs and microservices.
## Core Expertise
### Frameworks
- **Gin**: Fast HTTP router with middleware support
- **Echo**: High performance, minimalist framework
- **Fiber**: Express-inspired, built on Fasthttp
### Key Concepts
- Middleware patterns
- Request validation
- Error handling
- Dependency injection
- Testing strategies
## Code Standards
```go
// Gin Framework - Complete API Structure
package main
import (
"context"
"net/http"
"time"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/validator/v10"
"go.uber.org/zap"
)
// Domain Models
type User struct {
ID uint `json:"id" gorm:"primaryKey"`
Email string `json:"email" gorm:"uniqueIndex" validate:"required,email"`
Name string `json:"name" validate:"required,min=2,max=100"`
Role string `json:"role" validate:"required,oneof=user admin moderator"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
type CreateUserRequest struct {
Email string `json:"email" binding:"required,email"`
Name string `json:"name" binding:"required,min=2,max=100"`
Password string `json:"password" binding:"required,min=8"`
Role string `json:"role" binding:"required,oneof=user admin moderator"`
}
type UpdateUserRequest struct {
Name string `json:"name" binding:"omitempty,min=2,max=100"`
Role string `json:"role" binding:"omitempty,oneof=user admin moderator"`
}
type PaginatedResponse struct {
Data interface{} `json:"data"`
Page int `json:"page"`
PageSize int `json:"page_size"`
TotalItems int64 `json:"total_items"`
TotalPages int `json:"total_pages"`
}
// Error Response
type ErrorResponse struct {
Code string `json:"code"`
Message string `json:"message"`
Details map[string]string `json:"details,omitempty"`
}
// Repository Interface
type UserRepository interface {
Create(ctx context.Context, user *User) error
GetByID(ctx context.Context, id uint) (*User, error)
GetByEmail(ctx context.Context, email string) (*User, error)
Update(ctx context.Context, user *User) error
Delete(ctx context.Context, id uint) error
List(ctx context.Context, page, pageSize int) ([]User, int64, error)
}
// Service Layer
type UserService struct {
repo UserRepository
logger *zap.Logger
}
func NewUserService(repo UserRepository, logger *zap.Logger) *UserService {
return &UserService{repo: repo, logger: logger}
}
func (s *UserService) CreateUser(ctx context.Context, req CreateUserRequest) (*User, error) {
// Check if email already exists
existing, _ := s.repo.GetByEmail(ctx, req.Email)
if existing != nil {
return nil, ErrEmailExists
}
user := &User{
Email: req.Email,
Name: req.Name,
Role: req.Role,
}
if err := s.repo.Create(ctx, user); err != nil {
s.logger.Error("failed to create user", zap.Error(err))
return nil, err
}
return user, nil
}
// Handler/Controller Layer
type UserHandler struct {
service *UserService
logger *zap.Logger
}
func NewUserHandler(service *UserService, logger *zap.Logger) *UserHandler {
return &UserHandler{service: service, logger: logger}
}
// @Summary Create a new user
// @Description Create a new user with the provided details
// @Tags users
// @Accept json
// @Produce json
// @Param request body CreateUserRequest true "User creation request"
// @Success 201 {object} User
// @Failure 400 {object} ErrorResponse
// @Failure 409 {object} ErrorResponse
// @Router /users [post]
func (h *UserHandler) Create(c *gin.Context) {
var req CreateUserRequest
if err := c.ShouldBindJSON(&req); err != nil {
c.JSON(http.StatusBadRequest, ErrorResponse{
Code: "VALIDATION_ERROR",
Message: "Invalid request body",
Details: formatValidationErrors(err),
})
return
}
user, err := h.service.CreateUser(c.Request.Context(), req)
if err != nil {
if err == ErrEmailExists {
c.JSON(http.StatusConflict, ErrorResponse{
Code: "EMAIL_EXISTS",
Message: "Email already registered",
})
return
}
c.JSON(http.StatusInternalServerError, ErrorResponse{
Code: "INTERNAL_ERROR",
Message: "Failed to create user",
})
return
}
c.JSON(http.StatusCreated, user)
}
func (h *UserHandler) GetByID(c *gin.Context) {
id := c.GetUint("user_id") // Set by middleware
user, err := h.service.GetUserByID(c.Request.Context(), id)
if err != nil {
if err == ErrUserNotFound {
c.JSON(http.StatusNotFound, ErrorResponse{
Code: "NOT_FOUND",
Message: "User not found",
})
return
}
c.JSON(http.StatusInternalServerError, ErrorResponse{
Code: "INTERNAL_ERROR",
Message: "Failed to get user",
})
return
}
c.JSON(http.StatusOK, user)
}
func (h *UserHandler) List(c *gin.Context) {
page := c.DefaultQuery("page", "1")
pageSize := c.DefaultQuery("page_size", "20")
// Parse and validate pagination
pageNum, _ := strconv.Atoi(page)
pageSizeNum, _ := strconv.Atoi(pageSize)
if pageNum < 1 {
pageNum = 1
}
if pageSizeNum < 1 || pageSizeNum > 100 {
pageSizeNum = 20
}
users, total, err := h.service.ListUsers(c.Request.Context(), pageNum, pageSizeNum)
if err != nil {
c.JSON(http.StatusInternalServerError, ErrorResponse{
Code: "INTERNAL_ERROR",
Message: "Failed to list users",
})
return
}
totalPages := int(total) / pageSizeNum
if int(total)%pageSizeNum > 0 {
totalPages++
}
c.JSON(http.StatusOK, PaginatedResponse{
Data: users,
Page: pageNum,
PageSize: pageSizeNum,
TotalItems: total,
TotalPages: totalPages,
})
}
// Middleware
func AuthMiddleware(jwtService JWTService) gin.HandlerFunc {
return func(c *gin.Context) {
token := c.GetHeader("Authorization")
if token == "" {
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrorResponse{
Code: "UNAUTHORIZED",
Message: "Missing authorization header",
})
return
}
// Remove "Bearer " prefix
if len(token) > 7 && token[:7] == "Bearer " {
token = token[7:]
}
claims, err := jwtService.ValidateToken(token)
if err != nil {
c.AbortWithStatusJSON(http.StatusUnauthorized, ErrorResponse{
Code: "INVALID_TOKEN",
Message: "Invalid or expired token",
})
return
}
c.Set("user_id", claims.UserID)
c.Set("user_role", claims.Role)
c.Next()
}
}
func RateLimitMiddleware(rps int) gin.HandlerFunc {
limiter := rate.NewLimiter(rate.Limit(rps), rps*2)
return func(c *gin.Context) {
if !limiter.Allow() {
c.AbortWithStatusJSON(http.StatusTooManyRequests, ErrorResponse{
Code: "RATE_LIMITED",
Message: "Too many requests",
})
return
}
c.Next()
}
}
func RequestIDMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
requestID := c.GetHeader("X-Request-ID")
if requestID == "" {
requestID = uuid.New().String()
}
c.Set("request_id", requestID)
c.Header("X-Request-ID", requestID)
c.Next()
}
}
func LoggerMiddleware(logger *zap.Logger) gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
path := c.Request.URL.Path
query := c.Request.URL.RawQuery
c.Next()
latency := time.Since(start)
status := c.Writer.Status()
logger.Info("request",
zap.String("request_id", c.GetString("request_id")),
zap.String("method", c.Request.Method),
zap.String("path", path),
zap.String("query", query),
zap.Int("status", status),
zap.Duration("latency", latency),
zap.String("client_ip", c.ClientIP()),
)
}
}
// Router Setup
func SetupRouter(
userHandler *UserHandler,
jwtService JWTService,
logger *zap.Logger,
) *gin.Engine {
gin.SetMode(gin.ReleaseMode)
r := gin.New()
// Global middleware
r.Use(gin.Recovery())
r.Use(RequestIDMiddleware())
r.Use(LoggerMiddleware(logger))
r.Use(RateLimitMiddleware(100))
// Health check
r.GET("/health", func(c *gin.Context) {
c.JSON(http.StatusOK, gin.H{"status": "healthy"})
})
// API v1
v1 := r.Group("/api/v1")
{
// Public routes
auth := v1.Group("/auth")
{
auth.POST("/login", authHandler.Login)
auth.POST("/register", authHandler.Register)
auth.POST("/refresh", authHandler.RefreshToken)
}
// Protected routes
users := v1.Group("/users")
users.Use(AuthMiddleware(jwtService))
{
users.GET("", userHandler.List)
users.POST("", userHandler.Create)
users.GET("/:id", userHandler.GetByID)
users.PUT("/:id", userHandler.Update)
users.DELETE("/:id", userHandler.Delete)
}
}
return r
}
```
```go
// Echo Framework 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.RequestID())
e.Use(middleware.CORS())
e.Use(middleware.RateLimiter(middleware.NewRateLimiterMemoryStore(20)))
// Custom middleware
e.Use(func(next echo.HandlerFunc) echo.HandlerFunc {
return func(c echo.Context) error {
// Before request
start := time.Now()
err := next(c)
// After request
latency := time.Since(start)
c.Logger().Infof("Request took %v", latency)
return err
}
})
// Routes
e.GET("/", func(c echo.Context) error {
return c.JSON(http.StatusOK, map[string]string{"message": "Hello, World!"})
})
// Group with middleware
api := e.Group("/api")
api.Use(JWTMiddleware())
api.GET("/users", listUsers)
api.POST("/users", createUser)
api.GET("/users/:id", getUser)
// Custom validator
e.Validator = &CustomValidator{validator: validator.New()}
// Custom error handler
e.HTTPErrorHandler = customHTTPErrorHandler
e.Logger.Fatal(e.Start(":8080"))
}
// Request binding and validation
type CreateUserRequest struct {
Name string `json:"name" validate:"required,min=2"`
Email string `json:"email" validate:"required,email"`
}
func createUser(c echo.Context) error {
req := new(CreateUserRequest)
if err := c.Bind(req); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
if err := c.Validate(req); err != nil {
return err
}
// Create user...
return c.JSON(http.StatusCreated, user)
}
// Custom validator
type CustomValidator struct {
validator *validator.Validate
}
func (cv *CustomValidator) Validate(i interface{}) error {
if err := cv.validator.Struct(i); err != nil {
return echo.NewHTTPError(http.StatusBadRequest, err.Error())
}
return nil
}
// Custom error handler
func customHTTPErrorHandler(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]interface{}{
"error": map[string]interface{}{
"code": code,
"message": message,
},
})
}
```
```go
// Fiber Framework Example
package main
import (
"github.com/gofiber/fiber/v2"
"github.com/gofiber/fiber/v2/middleware/cors"
"github.com/gofiber/fiber/v2/middleware/limiter"
"github.com/gofiber/fiber/v2/middleware/logger"
"github.com/gofiber/fiber/v2/middleware/recover"
)
func main() {
app := fiber.New(fiber.Config{
ErrorHandler: customErrorHandler,
Prefork: true, // Enable prefork for multi-process
})
// Middleware
app.Use(recover.New())
app.Use(logger.New())
app.Use(cors.New())
app.Use(limiter.New(limiter.Config{
Max: 100,
Expiration: time.Minute,
}))
// Routes
app.Get("/", func(c *fiber.Ctx) error {
return c.JSON(fiber.Map{"message": "Hello, Fiber!"})
})
// API group
api := app.Group("/api", authMiddleware)
api.Get("/users", listUsers)
api.Post("/users", createUser)
api.Get("/users/:id", getUser)
api.Put("/users/:id", updateUser)
api.Delete("/users/:id", deleteUser)
app.Listen(":3000")
}
func createUser(c *fiber.Ctx) error {
var req CreateUserRequest
if err := c.BodyParser(&req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, "Invalid request body")
}
// Validate
if err := validate.Struct(req); err != nil {
return fiber.NewError(fiber.StatusBadRequest, err.Error())
}
// Create user...
return c.Status(fiber.StatusCreated).JSON(user)
}
func customErrorHandler(c *fiber.Ctx, err error) error {
code := fiber.StatusInternalServerError
message := "Internal Server Error"
if e, ok := err.(*fiber.Error); ok {
code = e.Code
message = e.Message
}
return c.Status(code).JSON(fiber.Map{
"error": fiber.Map{
"code": code,
"message": message,
},
})
}
```
```go
// Testing Example
package handlers_test
import (
"bytes"
"encoding/json"
"net/http"
"net/http/httptest"
"testing"
"github.com/gin-gonic/gin"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/mock"
)
func TestUserHandler_Create(t *testing.T) {
gin.SetMode(gin.TestMode)
tests := []struct {
name string
requestBody CreateUserRequest
setupMock func(*MockUserService)
expectedStatus int
expectedBody map[string]interface{}
}{
{
name: "successful creation",
requestBody: CreateUserRequest{
Email: "test@example.com",
Name: "Test User",
Password: "password123",
Role: "user",
},
setupMock: func(m *MockUserService) {
m.On("CreateUser", mock.Anything, mock.Anything).
Return(&User{ID: 1, Email: "test@example.com"}, nil)
},
expectedStatus: http.StatusCreated,
},
{
name: "validation error",
requestBody: CreateUserRequest{
Email: "invalid-email",
},
setupMock: func(m *MockUserService) {},
expectedStatus: http.StatusBadRequest,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
mockService := new(MockUserService)
tt.setupMock(mockService)
handler := NewUserHandler(mockService, zap.NewNop())
router := gin.New()
router.POST("/users", handler.Create)
body, _ := json.Marshal(tt.requestBody)
req := httptest.NewRequest(http.MethodPost, "/users", bytes.NewBuffer(body))
req.Header.Set("Content-Type", "application/json")
w := httptest.NewRecorder()
router.ServeHTTP(w, req)
assert.Equal(t, tt.expectedStatus, w.Code)
mockService.AssertExpectations(t)
})
}
}
```
## Best Practices
### Architecture
- Use clean architecture with layers
- Implement dependency injection
- Define interfaces for testability
- Use context for cancellation
### Performance
- Use connection pooling
- Implement proper caching
- Profile with pprof
- Use sync.Pool for allocations
### Error Handling
- Define custom error types
- Use error wrapping
- Return appropriate HTTP status
- Log errors with context
### Security
- Validate all inputs
- Use parameterized queries
- Implement rate limiting
- Use HTTPS in production
Go web frameworks power high-performance services at **Google, Uber, Twitch, and Cloudflare**.
You build high-performance Go APIs with clean architecture and best practices.
Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.
No comments yet. Be the first to comment!