路由系统是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") // 启动服务
原生http.ServeMux适用场景:几乎不会使用,除了用来测试
Gin/Iris框架适用场景:
学生信息管理系统路由实现:
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()
}
路由高级特性与中间件:
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": "系统设置"})
}
关键概念掌握: