做APP好还是建设网站好,东莞做网站哪个公司好,太原建站一条龙,做响应式网站应该注意什么文章目录 一 、增加路由二、书写流程控制#xff08;controller#xff09;逻辑三、书写业务逻辑四、与DB交互五、测试 代码地址#xff1a;https://gitee.com/lymgoforIT/bluebell
一 、增加路由
添加路由#xff0c;使用分组管理
v1 : r.Group(/api/v1)//… 文章目录 一 、增加路由二、书写流程控制controller逻辑三、书写业务逻辑四、与DB交互五、测试 代码地址https://gitee.com/lymgoforIT/bluebell
一 、增加路由
添加路由使用分组管理
v1 : r.Group(/api/v1)// 注册
v1.POST(/signup, controller.SignUpHandler)由于我们的项目是非常简单的上入门项目所以并不会用到DDD等复杂的目录设计和管理而是用了最基本的MVC三层结构。
controller目录用于接收路由进行基本的参数校验不做业务逻辑处理。logic目录用于处理业务逻辑。dao目录用于用数据源交互。
绿色即为本次注册功能需要新增的代码文件 二、书写流程控制controller逻辑
controller/user.go user.go文件主要负责用户的注册和登录。 这里首先写注册逻辑后续的登录逻辑也会在这个文件中实现。
package controllerimport (bluebell/modelsgithub.com/gin-gonic/gingithub.com/go-playground/validator/v10go.uber.org/zap
)// SignUpHandler 处理注册请求的函数
func SignUpHandler(c *gin.Context) {// 1. 获取参数和参数校验p : new(models.ParamSignUp)if err : c.ShouldBindJSON(p); err ! nil {// 请求参数有误直接返回响应zap.L().Error(SignUp with invalid param, zap.Error(err))// 判断err是不是validator.ValidationErrors 类型errs, ok : err.(validator.ValidationErrors)if !ok {ResponseError(c, CodeInvalidParam)return}ResponseErrorWithMsg(c, CodeInvalidParam, removeTopStruct(errs.Translate(trans)))return}// 2. 业务处理if err : logic.SignUp(p); err ! nil {zap.L().Error(logic.SignUp failed, zap.Error(err))if errors.Is(err, mysql.ErrorUserExist) {ResponseError(c, CodeUserExist)return}ResponseError(c, CodeServerBusy)return}// 3. 返回响应ResponseSuccess(c, nil)
}
代码说明
controller层不做业务逻辑主要就是组织整体流程的如参数校验业务处理返回响应。返回结果比较通用所以封装工具函数更为简介、易读。适当的定义一些错误码是不错的选择。
定义状态码并封装响应方法
controller/code.go
package controllertype ResCode int64const (CodeSuccess ResCode 1000 iotaCodeInvalidParamCodeUserExistCodeUserNotExistCodeInvalidPasswordCodeServerBusyCodeNeedLoginCodeInvalidToken
)var codeMsgMap map[ResCode]string{CodeSuccess: success,CodeInvalidParam: 请求参数错误,CodeUserExist: 用户名已存在,CodeUserNotExist: 用户名不存在,CodeInvalidPassword: 用户名或密码错误,CodeServerBusy: 服务繁忙,CodeNeedLogin: 需要登录,CodeInvalidToken: 无效的token,
}func (c ResCode) Msg() string {msg, ok : codeMsgMap[c]if !ok {msg codeMsgMap[CodeServerBusy]}return msg
}
controller/response.go
package controllerimport (net/httpgithub.com/gin-gonic/gin
)/*
{code: 10000, // 程序中的错误码msg: xx, // 提示信息data: {}, // 数据
}*/type ResponseData struct {Code ResCode json:codeMsg interface{} json:msgData interface{} json:data,omitempty
}func ResponseError(c *gin.Context, code ResCode) {c.JSON(http.StatusOK, ResponseData{Code: code,Msg: code.Msg(),Data: nil,})
}func ResponseErrorWithMsg(c *gin.Context, code ResCode, msg interface{}) {c.JSON(http.StatusOK, ResponseData{Code: code,Msg: msg,Data: nil,})
}func ResponseSuccess(c *gin.Context, data interface{}) {c.JSON(http.StatusOK, ResponseData{Code: CodeSuccess,Msg: CodeSuccess.Msg(),Data: data,})
}三、书写业务逻辑
首先我们需要查询DB中要注册的用户名是否已经存在所以需要先提供一个可以和DB交互的modeluser
models/user.go
提示可以直接SQL转对应的结构体 package modelsimport timetype User struct {ID int64 gorm:column:id db:id json:id form:idUserId int64 gorm:column:user_id db:user_id json:user_id form:user_idUsername string gorm:column:username db:username json:username form:usernamePassword string gorm:column:password db:password json:password form:passwordEmail string gorm:column:email db:email json:email form:emailGender int64 gorm:column:gender db:gender json:gender form:genderCreateTime time.Time gorm:column:create_time db:create_time json:create_time form:create_timeUpdateTime time.Time gorm:column:update_time db:update_time json:update_time form:update_time
}func (User) TableName() string {return user
}
logic/user.go 负责校验用户名是否已经存在若不存在则生成唯一的用户ID注册用户
import (bluebell/modelsbluebell/pkg/snowflake
)func SignUp(p *models.ParamSignUp) (err error) {// 1.判断用户存不存在if err : mysql.CheckUserExist(p.Username); err ! nil {return err}// 2.生成UIDuserID : snowflake.GenID()// 构造一个User实例user : models.User{UserID: userID,Username: p.Username,Password: p.Password,}// 3.保存进数据库return mysql.InsertUser(user)
}四、与DB交互
定义与DB交互时可能出现的相关错误码
dao/mysql/error_code.go
package mysqlimport errorsvar (ErrorUserExist errors.New(用户已存在)ErrorUserNotExist errors.New(用户不存在)ErrorInvalidPassword errors.New(用户名或密码错误)ErrorInvalidID errors.New(无效的ID)
)校验用户名是否已经存在、对密码加密、保存新注册的用户
dao/mysql/user.go
package mysqlimport (bluebell/modelscrypto/md5encoding/hex
)// 把每一步数据库操作封装成函数
// 待logic层根据业务需求调用const secret lym.com// CheckUserExist 检查指定用户名的用户是否存在
func CheckUserExist(username string) (err error) {var count int64if err : db.Model(models.User{}).Where(username ?, username).Count(count).Error; err ! nil {return err}if count 0 {return ErrorUserExist}return
}// InsertUser 想数据库中插入一条新的用户记录
func InsertUser(user *models.User) (err error) {// 对密码进行加密user.Password encryptPassword(user.Password)// 执行SQL语句入库u : models.User{UserId: user.UserId,Username: user.Username,Password: user.Password,}err db.Create(u).Errorreturn
}// encryptPassword 密码加密
func encryptPassword(oPassword string) string {h : md5.New()h.Write([]byte(secret))return hex.EncodeToString(h.Sum([]byte(oPassword)))
}
五、测试
编译
go build运行 ./bluebell.exe ./config/config.yaml注册因为lym已经存在所以会返回用户名已存在 注册一个不存在的名字试试成功
查询DB注册成功且密码是经过MD5加密过的实际就是123