flyfei

路由系统(原生http.ServeMux、第三方库gin/iris基础)

1. 语法讲解

路由系统是Web应用的交通指挥中心,负责将不同的HTTP请求分发到对应的处理函数。就像快递分拣系统,根据地址把包裹送到正确的收件人手中。

原生http.ServeMux - Go语言内置的路由器:

// 创建路由实例
mux := http.NewServeMux()

// 注册路由(路径 + 处理函数)
mux.HandleFunc("/", homeHandler)
mux.HandleFunc("/users", usersHandler)
mux.HandleFunc("/users/{id}", userDetailHandler)

// 启动服务器
http.ListenAndServe(":8080", mux)

第三方路由Gin - 高性能Web框架:

// 安装:go get -u github.com/gin-gonic/gin
router := gin.Default()  // 创建默认路由引擎

// 路由注册(支持RESTful方法)
router.GET("/users", getUsersHandler)  // http://localhost:80/users
router.POST("/users", createUserHandler)
router.PUT("/users/:id", updateUserHandler)
router.DELETE("/users/:id", deleteUserHandler)

router.Run(":8080")  // 启动服务

第三方路由Iris - 功能丰富的Web框架:

// 安装:go get github.com/kataras/iris/v12@latest
app := iris.New()  // 创建应用实例

// 路由注册
app.Get("/users", getUsersHandler)
app.Post("/users", createUserHandler)
app.Put("/users/{id:int}", updateUserHandler)

app.Listen(":8080")  // 启动服务

2. 应用场景

原生http.ServeMux适用场景:几乎不会使用,除了用来测试

Gin/Iris框架适用场景

3. 编程实例

学生信息管理系统路由实现

package main

import (
    "encoding/json"
    "fmt"
    "net/http"
    "strconv"
    
    "github.com/gin-gonic/gin"
)

// 学生数据结构
type Student struct {
    ID    int    `json:"id"`
    Name  string `json:"name"`
    Grade int    `json:"grade"`
    Major string `json:"major"`
}

// 模拟数据库
var students = []Student{
    {ID: 1, Name: "张三", Grade: 3, Major: "计算机科学"},
    {ID: 2, Name: "李四", Grade: 4, Major: "软件工程"},
}

// ========== Gin框架实现 ==========
func ginRouterDemo() {
    router := gin.Default()
    
    // 路由分组 - API v1
    apiV1 := router.Group("/api/v1")
    {
        studentsGroup := apiV1.Group("/students")
        {
            studentsGroup.GET("", getStudents)      // GET /api/v1/students
            studentsGroup.GET("/:id", getStudent)   // GET /api/v1/students/1
            studentsGroup.POST("", createStudent)   // POST /api/v1/students
            studentsGroup.PUT("/:id", updateStudent) // PUT /api/v1/students/1
        }
    }
    
    fmt.Println("Gin路由服务器运行在 :8081")
    router.Run(":8081")
}

// Gin处理函数
func getStudents(c *gin.Context) {
    c.JSON(200, gin.H{
        "data": students,
        "total": len(students),
    })
}

func getStudent(c *gin.Context) {
    id := c.Param("id")
    studentID, err := strconv.Atoi(id)
    if err != nil {
        c.JSON(400, gin.H{"error": "无效的学生ID"})
        return
    }
    
    for _, student := range students {
        if student.ID == studentID {
            c.JSON(200, gin.H{"data": student})
            return
        }
    }
    
    c.JSON(404, gin.H{"error": "学生不存在"})
}

func createStudent(c *gin.Context) {
    var newStudent Student
    if err := c.ShouldBindJSON(&newStudent); err != nil {
        c.JSON(400, gin.H{"error": "无效的请求数据"})
        return
    }
    
    // 生成新ID(模拟数据库操作)
    newStudent.ID = len(students) + 1
    students = append(students, newStudent)
    
    c.JSON(201, gin.H{
        "message": "创建成功",
        "data": newStudent,
    })
}

func updateStudent(c *gin.Context) {
    id := c.Param("id")
    studentID, err := strconv.Atoi(id)
    if err != nil {
        c.JSON(400, gin.H{"error": "无效的学生ID"})
        return
    }
    
    var updateData Student
    if err := c.ShouldBindJSON(&updateData); err != nil {
        c.JSON(400, gin.H{"error": "无效的请求数据"})
        return
    }
    
    // 查找并更新学生信息
    for i, student := range students {
        if student.ID == studentID {
            updateData.ID = studentID
            students[i] = updateData
            c.JSON(200, gin.H{
                "message": "更新成功",
                "data": updateData,
            })
            return
        }
    }
    
    c.JSON(404, gin.H{"error": "学生不存在"})
}

func main() {
    ginRouterDemo()
}

4. 其他用法

路由高级特性与中间件

package main

import (
    "github.com/gin-gonic/gin"
    "time"
)

func main() {
    router := gin.Default()
    
    // ========== 中间件使用 ==========
    
    // 全局中间件 - 日志记录
    router.Use(func(c *gin.Context) {
        start := time.Now()
        c.Next() // 继续处理请求
        duration := time.Since(start)
        fmt.Printf("请求 %s 处理时间: %v\n", c.Request.URL.Path, duration)
    })
    
    // 路由组中间件 - 认证检查
    authGroup := router.Group("/admin")
    authGroup.Use(authMiddleware)
    {
        authGroup.GET("/dashboard", adminDashboard)
        authGroup.GET("/settings", adminSettings)
    }
    
    // ========== 路由参数和查询参数 ==========
    router.GET("/search", func(c *gin.Context) {
        // 查询参数:/search?keyword=golang&page=1
        keyword := c.Query("keyword")
        page := c.DefaultQuery("page", "1") // 默认值
        
        c.JSON(200, gin.H{
            "keyword": keyword,
            "page": page,
        })
    })
    router.Run(":8080")
}

// 认证中间件
func authMiddleware(c *gin.Context) {
    token := c.GetHeader("Authorization")
    if token != "Bearer token" {
        c.JSON(401, gin.H{"error": "未授权访问"})
        c.Abort() // 停止后续处理
        return
    }
    c.Next()
}

func adminDashboard(c *gin.Context) {
    c.JSON(200, gin.H{"message": "管理员面板"})
}

func adminSettings(c *gin.Context) {
    c.JSON(200, gin.H{"message": "系统设置"})
}

5. 课时总结

关键概念掌握