|
|
3 days ago | |
|---|---|---|
| .. | ||
| config | 3 days ago | |
| push | 3 days ago | |
| router | 3 days ago | |
| static | 3 days ago | |
| templates | 3 days ago | |
| utils | 3 days ago | |
| .gitignore | 3 days ago | |
| README.md | 3 days ago | |
| config.yaml.example | 3 days ago | |
| go.mod | 3 days ago | |
| go.sum | 3 days ago | |
| main.go | 3 days ago | |
README.md
子千项目技能文档
1. 项目概述
子千项目是一个基于 Gin 框架开发的 Web 应用,提供了一套完整的工具函数库,用于简化开发流程和统一代码风格。本文档主要介绍项目中的核心工具函数,包括响应处理、身份验证、IP 处理等功能。
2. 核心工具包
2.1 utils/zi.go - 响应处理工具
Zi 是一个核心工具类,用于统一 API 响应格式,提供了多种响应方法,包括成功响应、错误响应、调试响应等。
2.1.1 Zi.Echo - 成功响应
功能:返回标准的成功响应,状态码为 200。
参数:
c *gin.Context- Gin 上下文对象data interface{}- 要返回的数据,可以是任意类型
返回格式:
{
"code": 200,
"message": "ok",
"data": {...}, // 传入的数据
"uuid": "..." // 请求 UUID
}
使用示例:
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来处理:// 推荐:简单成功响应 u.Zi.Echo(c, gin.H{}) // 不推荐:后端返回成功信息 u.Zi.Echo(c, gin.H{"result": "测试成功"}) // 成功信息应交给前端处理注意3:只有当需要返回具体数据时,才在
data中添加相应字段:// 推荐:返回具体数据 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- 可选参数,自定义错误码
返回格式:
{
"code": 100001, // 或自定义错误码
"message": "错误信息",
"data": {},
"uuid": "..."
}
使用示例:
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{}- 响应数据
返回格式:
{
"code": code,
"message": message,
"data": data,
"uuid": "..."
}
使用示例:
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{}- 调试数据
返回格式:
{
"code": 100000,
"message": "debug",
"data": {...}, // 调试数据
"uuid": "..."
}
使用示例:
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{}- 模板数据
使用示例:
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
使用示例:
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 地址
使用示例:
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- 解析错误
使用示例:
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 基本路由注册
功能:注册普通路由,无需身份验证。
示例代码:
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 路由,按模块分组管理。
示例代码:
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 子路由注册
功能:从子包注册路由,实现模块化管理。
示例代码:
// 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 响应格式的一致性。
核心规范:
-
禁止在
data中使用message字段:Zi.Echo会自动在响应根级别添加message字段(值为 "ok"),避免嵌套混乱。 -
简单成功响应只返回状态:对于简单的成功操作,后端只需要返回状态即可,成功信息由前端根据
code和message处理:// 推荐:简单成功响应 u.Zi.Echo(c, gin.H{}) // 不推荐:后端返回成功信息 u.Zi.Echo(c, gin.H{"result": "操作成功"}) // 成功信息应交给前端处理 -
仅在需要时返回数据:只有当需要返回具体业务数据时,才在
data中添加相应字段:// 推荐:返回具体数据 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 -
推荐格式示例:
// 简单成功响应 { "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 文件夹结构,需要使用别名导入不同模块的模型,以保持代码的清晰性和一致性。
核心约定:
-
admin 模块模型:使用
amod作为别名import ( amod "ziqian/models/admin" ) -
user 模块模型:使用
umod作为别名import ( umod "ziqian/models/user" )
使用示例:
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
// 业务逻辑...
}
注意事项:
- 严格按照模块使用对应的别名,避免混用
- 在所有导入模型的文件中保持一致的别名约定
- 当需要同时使用多个模块的模型时,同时导入多个别名
// 同时使用 admin 和 user 模块模型
import (
amod "ziqian/models/admin"
umod "ziqian/models/user"
)
5. 完整示例
5.1 实现一个完整的 API 路由
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),因为这种格式在前端展示时不够直观
使用示例:
// 错误:使用默认时间格式
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 位版本的可执行文件:
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 运行项目
使用以下命令直接运行项目:
go run main.go
10. 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 作者:子千项目组