# 子千项目技能文档 ## 1. 项目概述 子千项目是一个基于 Gin 框架开发的 Web 应用,提供了一套完整的工具函数库,用于简化开发流程和统一代码风格。本文档主要介绍项目中的核心工具函数,包括响应处理、身份验证、IP 处理等功能。 ## 2. 核心工具包 ### 2.1 utils/zi.go - 响应处理工具 `Zi` 是一个核心工具类,用于统一 API 响应格式,提供了多种响应方法,包括成功响应、错误响应、调试响应等。 #### 2.1.1 Zi.Echo - 成功响应 **功能**:返回标准的成功响应,状态码为 200。 **参数**: - `c *gin.Context` - Gin 上下文对象 - `data interface{}` - 要返回的数据,可以是任意类型 **返回格式**: ```json { "code": 200, "message": "ok", "data": {...}, // 传入的数据 "uuid": "..." // 请求 UUID } ``` **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func testHandler(c *gin.Context) { // 简单成功响应,仅返回状态 u.Zi.Echo(c, gin.H{}) // 返回复杂数据结构 userInfo := map[string]interface{}{ "id": 1, "name": "张三", "age": 25 } u.Zi.Echo(c, gin.H{"user": userInfo}) // 直接返回数据列表 users := []string{"user1", "user2", "user3"} u.Zi.Echo(c, gin.H{"users": users}) // 返回处理结果和相关数据 u.Zi.Echo(c, gin.H{"userId": 1001, "action": "create"}) } ``` **代码规范**: > 注意1:请不要在 `data` 中使用 `message` 字段,因为 `Zi.Echo` 方法会自动在响应根级别添加 `message` 字段(值为 "ok")。 > > 注意2:对于简单的成功响应,后端只需要返回状态即可,不需要在 `data` 中返回成功信息。成功信息应由前端根据返回的 `code` 和 `message` 来处理: > ```go > // 推荐:简单成功响应 > u.Zi.Echo(c, gin.H{}) > > // 不推荐:后端返回成功信息 > u.Zi.Echo(c, gin.H{"result": "测试成功"}) // 成功信息应交给前端处理 > ``` > > 注意3:只有当需要返回具体数据时,才在 `data` 中添加相应字段: > ```go > // 推荐:返回具体数据 > u.Zi.Echo(c, gin.H{"users": users}) > u.Zi.Echo(c, gin.H{"user": userInfo}) > ``` #### 2.1.2 Zi.Error - 错误响应 **功能**:返回标准的错误响应,默认状态码为 100001。 **参数**: - `c *gin.Context` - Gin 上下文对象 - `message string` - 错误信息 - `code ...int` - 可选参数,自定义错误码 **返回格式**: ```json { "code": 100001, // 或自定义错误码 "message": "错误信息", "data": {}, "uuid": "..." } ``` **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func testHandler(c *gin.Context) { // 使用默认错误码 u.Zi.Error(c, "参数错误") // 使用自定义错误码 u.Zi.Error(c, "权限不足", 403) // 在条件判断中使用 if !hasPermission { u.Zi.Error(c, "没有操作权限") return } } ``` #### 2.1.3 Zi.Exit - 自定义响应 **功能**:返回自定义的响应,包括状态码、消息和数据。 **参数**: - `c *gin.Context` - Gin 上下文对象 - `code int` - 状态码 - `message string` - 响应消息 - `data interface{}` - 响应数据 **返回格式**: ```json { "code": code, "message": message, "data": data, "uuid": "..." } ``` **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func testHandler(c *gin.Context) { // 自定义响应 u.Zi.Exit(c, 2001, "自定义成功", gin.H{"data": "自定义数据"}) } ``` #### 2.1.4 Zi.Debug - 调试响应 **功能**:返回调试响应,用于开发阶段调试。 **参数**: - `c *gin.Context` - Gin 上下文对象 - `data interface{}` - 调试数据 **返回格式**: ```json { "code": 100000, "message": "debug", "data": {...}, // 调试数据 "uuid": "..." } ``` **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func testHandler(c *gin.Context) { // 调试响应 u.Zi.Debug(c, gin.H{"request": c.Request}) } ``` #### 2.1.5 Zi.Html - HTML 响应 **功能**:返回 HTML 页面响应。 **参数**: - `c *gin.Context` - Gin 上下文对象 - `name string` - 模板名称 - `data interface{}` - 模板数据 **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func testHandler(c *gin.Context) { // 返回 HTML 页面 u.Zi.Html(c, "test.html", gin.H{"title": "测试页面"}) } ``` ### 2.2 utils/login.go - 身份验证工具 `Login` 工具类用于处理管理员身份验证和权限检查,提供了简洁的 API 用于保护需要登录的路由。 #### 2.2.1 Login.Admin - 管理员身份验证 **功能**:检查管理员是否登录,并验证权限。 **参数**: - `c *gin.Context` - Gin 上下文对象 - `mustAuth []string` - 必须具备的权限列表 - `oneAuth []string` - 至少具备一个的权限列表 **返回值**: - `bool` - 验证通过返回 true,否则返回 false **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) // 不需要权限的路由 func adminStatusHandler(c *gin.Context) { if !u.Login.Admin(c, []string{}, []string{}) { return } u.Zi.Echo(c, gin.H{"status": "online"}) } // 需要特定权限的路由 func adminUserHandler(c *gin.Context) { // 必须具备 user:read 权限 if !u.Login.Admin(c, []string{"user:read"}, []string{}) { return } u.Zi.Echo(c, gin.H{"users": []string{"user1", "user2"}}) } // 至少具备一个权限的路由 func adminActionHandler(c *gin.Context) { // 至少具备 create 或 update 权限 if !u.Login.Admin(c, []string{}, []string{"action:create", "action:update"}) { return } // 简单成功响应,仅返回状态 u.Zi.Echo(c, gin.H{}) } ``` ### 2.3 IP 处理工具 #### 2.3.1 GetClientIP - 获取客户端真实 IP **功能**:从请求头或上下文获取客户端的真实 IP 地址,支持代理转发。 **参数**: - `c *gin.Context` - Gin 上下文对象 **返回值**: - `string` - 客户端 IP 地址 **使用示例**: ```go package middleware import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func IpMiddleware(c *gin.Context) { clientIP := u.GetClientIP(c) c.Set("client_ip", clientIP) c.Next() } ``` #### 2.3.2 Zi.Region - IP 地址解析 **功能**:根据 IP 地址解析地理位置信息。 **参数**: - `ip string` - IP 地址字符串 **返回值**: - `string` - 地理位置信息,格式如 "省份|城市|运营商" - `error` - 解析错误 **使用示例**: ```go package utils import ( "log" ) func testIpRegion() { ip := "8.8.8.8" region, err := Zi.Region(ip) if err != nil { log.Printf("IP 解析错误: %v", err) return } log.Printf("IP %s 所属地区: %s", ip, region) } ``` ## 3. 路由注册示例 ### 3.1 基本路由注册 **功能**:注册普通路由,无需身份验证。 **示例代码**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func SetupRouter() *gin.Engine { r := gin.Default() // 注册普通路由 r.GET("/", func(c *gin.Context) { u.Zi.Echo(c, gin.H{"welcome": "欢迎访问子千项目"}) }) return r } ``` ### 3.2 API 路由注册 **功能**:注册 API 路由,按模块分组管理。 **示例代码**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func RegisterAdminRoutes(router *gin.RouterGroup) { group := router.Group("/admin") { group.POST("/login", adminLoginHandler) group.POST("/status", adminStatusHandler) group.POST("/info", adminInfoHandler) group.POST("/menu", adminMenuHandler) } } func RegisterApiRoutes(r *gin.Engine) { apiGroup := r.Group("/api") { RegisterAdminRoutes(apiGroup) // 注册其他模块路由 } } ``` ### 3.3 子路由注册 **功能**:从子包注册路由,实现模块化管理。 **示例代码**: ```go // router/admin.go package router import ( "ziqian/router/admin" "github.com/gin-gonic/gin" ) func RegisterAdminRoutes(router *gin.RouterGroup) { group := router.Group("/admin") { // 注册基础路由 group.POST("/login", adminLoginHandler) // 从子包注册路由 admin.RegisterAdminChangeRoutes(group) } } // router/admin/change.go package admin import ( u "ziqian/utils" "github.com/gin-gonic/gin" ) func RegisterAdminChangeRoutes(router *gin.RouterGroup) { group := router.Group("/change") { group.POST("/info", adminChangeInfoHandler) group.POST("/password", adminChangePasswordHandler) } } ``` ## 4. 最佳实践 ### 4.1 统一响应格式 在所有 API 路由中使用 `Zi` 工具类返回响应,保持 API 响应格式的一致性。 **核心规范**: 1. **禁止在 `data` 中使用 `message` 字段**:`Zi.Echo` 会自动在响应根级别添加 `message` 字段(值为 "ok"),避免嵌套混乱。 2. **简单成功响应只返回状态**:对于简单的成功操作,后端只需要返回状态即可,成功信息由前端根据 `code` 和 `message` 处理: ```go // 推荐:简单成功响应 u.Zi.Echo(c, gin.H{}) // 不推荐:后端返回成功信息 u.Zi.Echo(c, gin.H{"result": "操作成功"}) // 成功信息应交给前端处理 ``` 3. **仅在需要时返回数据**:只有当需要返回具体业务数据时,才在 `data` 中添加相应字段: ```go // 推荐:返回具体数据 u.Zi.Echo(c, gin.H{"users": users}) // 返回用户列表 u.Zi.Echo(c, gin.H{"user": userInfo}) // 返回用户信息 u.Zi.Echo(c, gin.H{"userId": 1001}) // 返回新创建的用户ID ``` 4. **推荐格式示例**: ```json // 简单成功响应 { "code": 200, "message": "ok", "data": {}, "uuid": "..." } // 返回具体数据 { "code": 200, "message": "ok", "data": { "users": ["user1", "user2", "user3"] }, "uuid": "..." } ``` ### 4.2 权限验证 对于需要登录的路由,使用 `Login.Admin` 方法进行身份验证和权限检查,确保 API 安全。 ### 4.3 错误处理 使用 `Zi.Error` 方法返回错误信息,提供明确的错误码和错误描述,方便前端处理。 ### 4.4 模块化路由 按功能模块组织路由,使用子包注册路由,提高代码的可维护性和扩展性。 ### 4.5 模型导入别名约定 了解 `models` 文件夹结构,需要使用别名导入不同模块的模型,以保持代码的清晰性和一致性。 **核心约定**: 1. **admin 模块模型**:使用 `amod` 作为别名 ```go import ( amod "ziqian/models/admin" ) ``` 2. **user 模块模型**:使用 `umod` 作为别名 ```go import ( umod "ziqian/models/user" ) ``` **使用示例**: ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" "ziqian/database" amod "ziqian/models/admin" umod "ziqian/models/user" ) // 使用 admin 模块模型 func getAdminListHandler(c *gin.Context) { var admins []amod.Admin // 业务逻辑... } // 使用 user 模块模型 func getUserListHandler(c *gin.Context) { var users []umod.User // 业务逻辑... } ``` **注意事项**: - 严格按照模块使用对应的别名,避免混用 - 在所有导入模型的文件中保持一致的别名约定 - 当需要同时使用多个模块的模型时,同时导入多个别名 ```go // 同时使用 admin 和 user 模块模型 import ( amod "ziqian/models/admin" umod "ziqian/models/user" ) ``` ## 5. 完整示例 ### 5.1 实现一个完整的 API 路由 ```go package router import ( u "ziqian/utils" "github.com/gin-gonic/gin" "ziqian/database" amod "ziqian/models/admin" umod "ziqian/models/user" ) func RegisterUserRoutes(router *gin.RouterGroup) { group := router.Group("/user") { group.GET("/list", getUserListHandler) group.GET("/info", getUserInfoHandler) group.POST("/create", createUserHandler) group.POST("/update", updateUserHandler) group.POST("/delete", deleteUserHandler) } } func getUserListHandler(c *gin.Context) { if !u.Login.Admin(c, []string{"user:read"}, []string{}) { return } db := database.GetDB("main") if db == nil { u.Zi.Error(c, "数据库连接失败") return } var users []umod.User if err := db.Find(&users).Error; err != nil { u.Zi.Error(c, "获取用户列表失败") return } u.Zi.Echo(c, gin.H{"users": users}) } func getUserInfoHandler(c *gin.Context) { if !u.Login.Admin(c, []string{"user:read"}, []string{}) { return } // 实现获取用户信息逻辑 userInfo := map[string]interface{}{ "id": 1, "name": "张三", "age": 25 } u.Zi.Echo(c, gin.H{"user": userInfo}) } func createUserHandler(c *gin.Context) { if !u.Login.Admin(c, []string{"user:create"}, []string{}) { return } // 实现创建用户逻辑 // 如果需要返回新创建的用户ID,可以这样做 u.Zi.Echo(c, gin.H{"userId": 1001}) // 如果不需要返回数据,直接返回空即可 // u.Zi.Echo(c, gin.H{}) } func updateUserHandler(c *gin.Context) { if !u.Login.Admin(c, []string{"user:update"}, []string{}) { return } // 实现更新用户逻辑 // 简单更新操作,只返回状态 u.Zi.Echo(c, gin.H{}) } func deleteUserHandler(c *gin.Context) { if !u.Login.Admin(c, []string{"user:delete"}, []string{}) { return } // 实现删除用户逻辑 // 简单删除操作,只返回状态 u.Zi.Echo(c, gin.H{}) } ``` ## 6. 总结 本文档介绍了子千项目中的核心工具函数,包括响应处理、身份验证、IP 处理等功能。通过使用这些工具函数,可以简化开发流程,统一代码风格,提高代码的可维护性和扩展性。 在实际开发中,建议按照本文档中的最佳实践使用这些工具函数,确保 API 设计的一致性和安全性。 ## 7. 后续更新 本文档将随着项目的发展不断更新,新增的功能和工具函数将及时添加到文档中。 ## 8. 注意事项 ### 8.1 时间格式化规范 **功能**:统一 API 响应中的时间格式,确保前端展示一致性。 **规范**: - 所有时间字段(如 `created_at`、`updated_at`)应使用 `Format("2006-01-02 15:04:05")` 进行格式化 - 格式化后的时间格式为:`2026-01-31 15:28:07` - 避免使用默认的 RFC3339 格式(如 `2026-01-31T15:28:07+08:00`),因为这种格式在前端展示时不够直观 **使用示例**: ```go // 错误:使用默认时间格式 resultList = append(resultList, map[string]interface{}{ "created_at": item.CreatedAt, // 会返回 RFC3339 格式 "updated_at": item.UpdatedAt }) // 正确:使用标准时间格式 resultList = append(resultList, map[string]interface{}{ "created_at": item.CreatedAt.Format("2006-01-02 15:04:05"), "updated_at": item.UpdatedAt.Format("2006-01-02 15:04:05") }) ``` **适用范围**: - 所有 API 响应中的时间字段 - 特别是列表接口(如 `/api/admin/admin/list`)中的时间展示 --- ## 9. 项目构建与运行 ### 9.1 构建项目 使用以下命令构建 Linux 64 位版本的可执行文件: ```bash GOOS=linux GOARCH=amd64 go build -o build/ziqian-linux-amd64-$(date +%Y%m%d%H%M) main.go GOOS=windows GOARCH=amd64 go build -o build/ziqian-windows-amd64-$(date +%Y%m%d%H%M).exe main.go ``` ### 9.2 运行项目 使用以下命令直接运行项目: ```bash go run main.go ``` --- ## 10. Nginx 配置 以下是项目的 Nginx 配置示例,用于部署到生产环境: ```nginx # mana 管理目录(无缓存,内容频繁变动) location /mana/ { root /data/web/ziqian.online/golang/hoho; autoindex off; # 关闭目录列表(安全) expires -1; # 完全禁止缓存,确保获取最新内容 add_header Cache-Control "no-store, no-cache, must-revalidate, proxy-revalidate"; add_header Pragma "no-cache"; # 兼容旧浏览器 add_header Expires "0"; # 立即过期 try_files $uri $uri/ =404; } # static 静态目录(长期缓存,资源稳定) location /static/ { root /data/web/ziqian.online/golang/hoho; autoindex off; expires 30d; add_header Cache-Control "public, max-age=2592000"; try_files $uri $uri/ =404; } # upload 上传目录(无缓存+请求限制) location /upload/ { root /data/web/ziqian.online/golang/hoho; autoindex off; expires -1; add_header Cache-Control "no-store, no-cache, must-revalidate"; try_files $uri $uri/ =404; # 仅允许GET/HEAD请求,防止恶意上传 limit_except GET HEAD { deny all; } } ``` --- **文档版本**:1.0.0 **更新时间**:2026-02-08 **作者**:子千项目组