2024-08-14
Go & 后端
00

目录

1 建表
2 Swagger-Gin使用
3 获取题目列表

MisakaOJ项目,第一次记录内容

1 建表

  1. 题目表
    • identity,varchar,长度36,作为题目的唯一标识
    • cid,varchar,长度255,作为题目的分类
    • title,varchar,长度255,作为题目的标题
    • content,varchar,长度255,作为题目的正文
    • max_runtime,int,长度11,题目最大运行时间
    • max_memory,int,长度11,题目最大运行内存
go
type Question struct { gorm.Model Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` // 题目唯一标识 CategoryId string `gorm:"column:category_id;type:varchar(255);" json:"category_id"` // 分类ID 以逗号分割 Title string `gorm:"column:title;type:varchar(255);" json:"title"` // 题目标题 Content string `gorm:"column:content;type:text;" json:"content"` // 题目正文 MaxRuntime int `gorm:"column:max_runtime;type:int(11)" json:"max_runtime"` // 最大运行时长 MaxMem int `gorm:"column:max_memory;type:int(11)" json:"max_mem"` // 最大允许内存 } func (table *Question) TableName() string { return "question" }
  1. 用户表
    • identity,varchar,长度36,唯一标识
    • name,varchar,长度100,用户名
    • password,varchar,长度32,用户密码,md5加密
    • phone,varchar,长度20,用户手机号
    • mail,varchar,长度100,用户邮箱
go
type User struct { gorm.Model Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` // 用户唯一标识 Name string `gorm:"column:user;type:varchar(100);" json:"name"` // 用户名 Password string `gorm:"column:password;type:varchar(32);" json:"password"` // 密码 加密后 Phone string `gorm:"column:phone;type:varchar(20)" json:"phone"` // 手机号 Mail string `gorm:"column:mail;type:varchar(100);" json:"mail"` // 邮箱地址 } func (table *User) TableName() string { return "user" }
  1. 分类表
    • identity,varchar,长度36,唯一标识
    • name,varchar,长度100,分类名称
    • parent_id,int,长度11,父级id,自身为顶级时默认为0
go
type Category struct { gorm.Model Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` // 分类唯一标识 Name string `gorm:"column:user;type:varchar(100);" json:"name"` // 分类名称 ParentId int `gorm:"column:parent_id;type:int(11);default:0" json:"parent_id"` // 父级ID 自身为顶级是默认为0 } func (table *Category) TableName() string { return "category" }
  1. 提交记录表
    • identity,varchar,长度36,唯一标识
    • problem_identity,varchar,长度36,问题唯一标识
    • user_identity,varchar,长度36,用户唯一标识
    • path,varchar,长度255,代码保存位置路径
    • status,tinyint,长度1,提交记录状态,默认为0待判断,1为答案正确,2为答案错误,3运行超时,4运行超过最大内存
go
type Submit struct { gorm.Model Identity string `gorm:"column:identity;type:varchar(36);" json:"identity"` // 提交记录唯一标识 ProblemIdentity string `gorm:"column:problem_identity;type:varchar(36);" json:"problem_identity"` // 问题唯一标识 UserIdentity string `gorm:"column:user_identity;type:varchar(36);" json:"user_identity"` // 用户唯一标识 Path string `gorm:"column:path;type:varchar(255);" json:"path"` // 保存提交代码位置的路径 Status int `gorm:"column:status;type:tinyint(1);default:0;" json:"status"` // 提交记录状态 } func (table *Submit) TableName() string { return "submit" }

2 Swagger-Gin使用

安装

bash
go get -u github.com/swaggo/gin-swagger go install github.com/swaggo/swag/cmd/swag@latest go get -u github.com/swaggo/files

使用

  1. 命令行输入swag init即可在该位置下快速生成/更新docs包以及其中的文件
  2. 命令行输入swag -v查看swag版本号
  3. 在gin的路由器上加入swagger:r.GET("/swagger/*any", ginSwagger.WrapHandler(swaggerFiles.Handler)),并且在include中以匿名方式加入刚才生成的docs包。URL路径可以自己指定。
  4. 运行即可在xxxxx/swagger/index.html下访问Swagger文档。

为一个接口编写注释以快速生成Swagger

假设现在有这么一个接口:

go
func GetQuestionList(c *gin.Context) { page, err := strconv.Atoi(c.DefaultQuery("page", constants.DefaultPage)) if err != nil { log.Println("Get Param Error: ", err) return } size, err := strconv.Atoi(c.DefaultQuery("size", constants.DefaultSize)) if err != nil { log.Println("Get Param Error: ", err) return } keyword := c.Query("keyword") // 中间省略 c.JSON(http.StatusOK, gin.H{ "code": 200, "data": gin.H{ "list": result, "count": count, }, }) }

为其添加注解可以帮助Swagger-Gin快速生成文档,比如:

go
// @Tags 公共方法 // @Summary 获取问题列表 // @Param page query int false "page" // @Param size query int false "size" // @Param keyword query string false "keyword" // @Success 200 {data} json "{"code": "200", "data": ""}" // @Router /question-list [get] func GetQuestionList(c *gin.Context) { page, err := strconv.Atoi(c.DefaultQuery("page", constants.DefaultPage)) if err != nil { log.Println("Get Param Error: ", err) return } size, err := strconv.Atoi(c.DefaultQuery("size", constants.DefaultSize)) if err != nil { log.Println("Get Param Error: ", err) return } keyword := c.Query("keyword") // 中间省略 c.JSON(http.StatusOK, gin.H{ "code": 200, "data": gin.H{ "list": result, "count": count, }, }) }

可以通过注解被添加到文档中的信息有以下类别:

注解含义示例
description该接口的详细说明@Description xxx
tags该接口的类别@Tags xxx
summary该接口的简短说明@Summary xxx
accept该接口接受数据类型@Accept json
produce该接口返回的数据的类型@Produce json
param该接口的参数 这个注解可以有多行 每一行代表一种参数@Param 参数名 参数类型 数据类型 是否必须 注释 属性(可选)
success该接口成功返回的结果@Success 返回码 {参数类型} 数据类型 注释
failure该接口失败返回的结果同success
response该接口返回结果说明同success
router该接口的路径@Router xxx

更多信息可以查看官方文档

3 获取题目列表

go
// GetQuestionList // @Tags 公共方法 // @Summary 获取问题列表 // @Param page query int false "page" // @Param size query int false "size" // @Param keyword query string false "keyword" // @Success 200 {data} json "{"code": "200", "data": ""}" // @Router /question-list [get] func GetQuestionList(c *gin.Context) { page, err := strconv.Atoi(c.DefaultQuery("page", constants.DefaultPage)) if err != nil { log.Println("Get Param Error: ", err) return } size, err := strconv.Atoi(c.DefaultQuery("size", constants.DefaultSize)) if err != nil { log.Println("Get Param Error: ", err) return } page = (page - 1) * size // page到offset的转换 keyword := c.Query("keyword") var count int64 // tx是transaction的缩写 tx := models.GetQuestionList(keyword) result := make([]*models.Question, 0) err = tx.Count(&count).Omit("content").Offset(page).Limit(size).Find(&result).Error // Omit 指定一行要忽略的数据 if err != nil { log.Println("Get Problem List Error: ", err) return } c.JSON(http.StatusOK, gin.H{ "code": 200, "data": gin.H{ "list": result, "count": count, }, }) } func GetQuestionList(keyword string) *gorm.DB { return DB.Model(new(Question)).Where("title like ? OR content like ?", "%"+keyword+"%", "%"+keyword+"%") }

本文作者:御坂19327号

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!