// 路由分组与中间件
func setupRouter() *gin.Engine {
r := gin.Default()
// 全局中间件
r.Use(gin.Logger())
r.Use(gin.Recovery())
// API路由组
api := r.Group("/api/v1")
{
// 用户相关路由
users := api.Group("/users")
{
users.GET("", userHandler.ListUsers)
users.POST("", userHandler.CreateUser)
users.GET("/:id", userHandler.GetUser)
users.PUT("/:id", userHandler.UpdateUser)
users.DELETE("/:id", userHandler.DeleteUser)
}
// 商品相关路由
products := api.Group("/products")
{
products.GET("", productHandler.ListProducts)
products.POST("", productHandler.CreateProduct)
products.GET("/:id", productHandler.GetProduct)
}
}
return r
}
// 日志中间件
func LoggerMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
start := time.Now()
c.Next()
latency := time.Since(start)
status := c.Writer.Status()
method := c.Request.Method
path := c.Request.URL.Path
log.Printf("[%s] %s %d %s", method, path, status, latency)
}
}
// 限流中间件
func RateLimitMiddleware(limit int) gin.HandlerFunc {
limiter := rate.NewLimiter(rate.Limit(limit), limit)
return func(c *gin.Context) {
if !limiter.Allow() {
c.JSON(429, gin.H{"error": "请求过于频繁"})
c.Abort()
return
}
c.Next()
}
}
// CORS中间件
func CORSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
c.Writer.Header().Set("Access-Control-Allow-Methods", "GET, POST, PUT, DELETE, OPTIONS")
c.Writer.Header().Set("Access-Control-Allow-Headers", "Content-Type, Authorization")
if c.Request.Method == "OPTIONS" {
c.AbortWithStatus(204)
return
}
c.Next()
}
}
// 复杂数据绑定
type CreateProductRequest struct {
Name string `json:"name" binding:"required,min=2,max=100"`
Description string `json:"description" binding:"max=500"`
Price float64 `json:"price" binding:"required,min=0"`
Stock int `json:"stock" binding:"min=0"`
CategoryID uint `json:"category_id" binding:"required"`
Images []string `json:"images"`
}
// 文件上传处理
func UploadHandler(c *gin.Context) {
file, err := c.FormFile("file")
if err != nil {
c.JSON(400, gin.H{"error": "文件上传失败"})
return
}
// 验证文件类型
allowedTypes := map[string]bool{
"image/jpeg": true,
"image/png": true,
"image/gif": true,
}
if !allowedTypes[file.Header.Get("Content-Type")] {
c.JSON(400, gin.H{"error": "不支持的文件类型"})
return
}
// 保存文件
filename := fmt.Sprintf("uploads/%s", file.Filename)
if err := c.SaveUploadedFile(file, filename); err != nil {
c.JSON(500, gin.H{"error": "文件保存失败"})
return
}
c.JSON(200, gin.H{"message": "上传成功", "filename": filename})
}
// 统一响应格式
type APIResponse struct {
Code int `json:"code"`
Message string `json:"message"`
Data interface{} `json:"data,omitempty"`
Meta *MetaInfo `json:"meta,omitempty"`
}
type MetaInfo struct {
Page int `json:"page"`
PageSize int `json:"page_size"`
Total int `json:"total"`
TotalPage int `json:"total_page"`
}
// 成功响应
func SuccessResponse(data interface{}) APIResponse {
return APIResponse{
Code: 200,
Message: "success",
Data: data,
}
}
// 分页响应
func PaginatedResponse(data interface{}, page, pageSize, total int) APIResponse {
totalPage := (total + pageSize - 1) / pageSize
return APIResponse{
Code: 200,
Message: "success",
Data: data,
Meta: &MetaInfo{
Page: page,
PageSize: pageSize,
Total: total,
TotalPage: totalPage,
},
}
}
// JWT服务
type JWTService struct {
secretKey []byte
}
func NewJWTService(secret string) *JWTService {
return &JWTService{
secretKey: []byte(secret),
}
}
func (j *JWTService) GenerateToken(userID uint, roles []string) (string, error) {
claims := jwt.MapClaims{
"user_id": userID,
"roles": roles,
"exp": time.Now().Add(24 * time.Hour).Unix(),
}
token := jwt.NewWithClaims(jwt.SigningMethodHS256, claims)
return token.SignedString(j.secretKey)
}
func (j *JWTService) ValidateToken(tokenString string) (jwt.MapClaims, error) {
token, err := jwt.Parse(tokenString, func(token *jwt.Token) (interface{}, error) {
if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
return nil, fmt.Errorf("unexpected signing method: %v", token.Header["alg"])
}
return j.secretKey, nil
})
if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
return claims, nil
}
return nil, err
}
// 基于角色的权限控制
func RoleBasedAuth(requiredRoles ...string) gin.HandlerFunc {
return func(c *gin.Context) {
claims, exists := c.Get("claims")
if !exists {
c.JSON(401, gin.H{"error": "未授权"})
c.Abort()
return
}
jwtClaims := claims.(jwt.MapClaims)
userRoles, ok := jwtClaims["roles"].([]interface{})
if !ok {
c.JSON(403, gin.H{"error": "权限不足"})
c.Abort()
return
}
// 检查用户角色是否包含所需角色
hasPermission := false
for _, requiredRole := range requiredRoles {
for _, userRole := range userRoles {
if userRole == requiredRole {
hasPermission = true
break
}
}
}
if !hasPermission {
c.JSON(403, gin.H{"error": "权限不足"})
c.Abort()
return
}
c.Next()
}
}
// WebSocket连接管理
type ConnectionManager struct {
connections map[*websocket.Conn]bool
broadcast chan []byte
register chan *websocket.Conn
unregister chan *websocket.Conn
mutex sync.RWMutex
}
func NewConnectionManager() *ConnectionManager {
return &ConnectionManager{
connections: make(map[*websocket.Conn]bool),
broadcast: make(chan []byte),
register: make(chan *websocket.Conn),
unregister: make(chan *websocket.Conn),
}
}
func (cm *ConnectionManager) Run() {
for {
select {
case conn := <-cm.register:
cm.mutex.Lock()
cm.connections[conn] = true
cm.mutex.Unlock()
case conn := <-cm.unregister:
cm.mutex.Lock()
if _, ok := cm.connections[conn]; ok {
delete(cm.connections, conn)
conn.Close()
}
cm.mutex.Unlock()
case message := <-cm.broadcast:
cm.mutex.RLock()
for conn := range cm.connections {
if err := conn.WriteMessage(websocket.TextMessage, message); err != nil {
cm.unregister <- conn
}
}
cm.mutex.RUnlock()
}
}
}
// WebSocket处理器
func WebSocketHandler(cm *ConnectionManager) gin.HandlerFunc {
var upgrader = websocket.Upgrader{
CheckOrigin: func(r *http.Request) bool {
return true
},
}
return func(c *gin.Context) {
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil {
log.Printf("WebSocket升级失败: %v", err)
return
}
cm.register <- conn
defer func() {
cm.unregister <- conn
}()
for {
messageType, message, err := conn.ReadMessage()
if err != nil {
break
}
// 处理接收到的消息
if messageType == websocket.TextMessage {
cm.broadcast <- message
}
}
}
}
// HTML模板渲染
func setupTemplateEngine() *gin.Engine {
r := gin.Default()
// 加载模板
r.LoadHTMLGlob("templates/*")
// 静态文件服务
r.Static("/static", "./static")
r.StaticFile("/favicon.ico", "./static/favicon.ico")
return r
}
// 模板处理器
func HomeHandler(c *gin.Context) {
c.HTML(200, "index.html", gin.H{
"title": "首页",
"user": gin.H{
"name": "张三",
"email": "[email protected]",
},
})
}
// 多文件上传
type UploadService struct {
cloudStorage CloudStorage
}
func (us *UploadService) UploadMultipleFiles(files []*multipart.FileHeader) ([]string, error) {
var uploadedFiles []string
for _, file := range files {
filename, err := us.uploadSingleFile(file)
if err != nil {
return nil, err
}
uploadedFiles = append(uploadedFiles, filename)
}
return uploadedFiles, nil
}
func (us *UploadService) uploadSingleFile(file *multipart.FileHeader) (string, error) {
// 打开文件
src, err := file.Open()
if err != nil {
return "", err
}
defer src.Close()
// 生成唯一文件名
ext := filepath.Ext(file.Filename)
filename := fmt.Sprintf("%s%s", uuid.New().String(), ext)
// 上传到云存储
if err := us.cloudStorage.Upload(filename, src); err != nil {
return "", err
}
return filename, nil
}
// Redis缓存服务
type CacheService struct {
client *redis.Client
}
func NewCacheService(addr, password string) *CacheService {
client := redis.NewClient(&redis.Options{
Addr: addr,
Password: password,
DB: 0,
})
return &CacheService{client: client}
}
func (cs *CacheService) Set(key string, value interface{}, expiration time.Duration) error {
return cs.client.Set(context.Background(), key, value, expiration).Err()
}
func (cs *CacheService) Get(key string) (string, error) {
return cs.client.Get(context.Background(), key).Result()
}
func (cs *CacheService) Delete(key string) error {
return cs.client.Del(context.Background(), key).Err()
}
// Session管理
func SessionMiddleware(store sessions.Store) gin.HandlerFunc {
return func(c *gin.Context) {
session, _ := store.Get(c.Request, "session-name")
c.Set("session", session)
c.Next()
session.Save(c.Request, c.Writer)
}
}
// 数据库连接池优化
func setupDatabase() *sql.DB {
db, err := sql.Open("mysql", "user:password@tcp(localhost:3306)/dbname")
if err != nil {
log.Fatal(err)
}
// 连接池配置
db.SetMaxOpenConns(25)
db.SetMaxIdleConns(25)
db.SetConnMaxLifetime(5 * time.Minute)
return db
}
// 响应压缩
func CompressionMiddleware() gin.HandlerFunc {
return gin.Gzip(gin.DefaultCompression)
}
// 静态资源缓存
func StaticCacheMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
if strings.HasPrefix(c.Request.URL.Path, "/static/") {
c.Header("Cache-Control", "public, max-age=31536000")
}
c.Next()
}
}
// SQL注入防护
func SafeQuery(db *sql.DB, query string, args ...interface{}) (*sql.Rows, error) {
// 使用参数化查询
return db.Query(query, args...)
}
// XSS防护
func XSSMiddleware() gin.HandlerFunc {
return func(c *gin.Context) {
c.Header("X-XSS-Protection", "1; mode=block")
c.Header("X-Content-Type-Options", "nosniff")
c.Next()
}
}
// CSRF防护
func CSRFMiddleware(secret string) gin.HandlerFunc {
return csrf.Middleware(csrf.Options{
Secret: secret,
ErrorFunc: func(c *gin.Context) {
c.JSON(403, gin.H{"error": "CSRF token验证失败"})
c.Abort()
},
})
}
// 项目结构
ecommerce-platform/
├── cmd/
│ ├── api/ # API服务器
│ └── admin/ # 后台管理
├── internal/
│ ├── config/ # 配置管理
│ ├── handler/ # HTTP处理器
│ ├── middleware/ # 中间件
│ ├── model/ # 数据模型
│ ├── repository/ # 数据访问层
│ ├── service/ # 业务逻辑层
│ └── utils/ # 工具函数
├── pkg/
│ ├── auth/ # 认证模块
│ ├── cache/ # 缓存模块
│ ├── payment/ # 支付模块
│ └── storage/ # 存储模块
└── web/ # 前端资源
├── static/
└── templates/
// 购物车服务
type CartService struct {
cartRepo repository.CartRepository
productRepo repository.ProductRepository
}
func (cs *CartService) AddToCart(userID, productID uint, quantity int) error {
// 检查商品库存
product, err := cs.productRepo.FindByID(productID)
if err != nil {
return err
}
if product.Stock < quantity {
return errors.New("库存不足")
}
// 添加商品到购物车
return cs.cartRepo.AddItem(userID, productID, quantity)
}
// 订单服务
type OrderService struct {
orderRepo repository.OrderRepository
paymentRepo repository.PaymentRepository
}
func (os *OrderService) CreateOrder(userID uint, cartItems []model.CartItem) (*model.Order, error) {
// 计算总价
var totalAmount float64
for _, item := range cartItems {
totalAmount += item.Product.Price * float64(item.Quantity)
}
// 创建订单
order := &model.Order{
UserID: userID,
TotalAmount: totalAmount,
Status: model.OrderStatusPending,
}
return os.orderRepo.Create(order)
}
这个Web开发特训章节将帮助您系统掌握Go语言Web开发的全套技能,为成为全栈开发工程师奠定坚实基础。