2025年BlueBell注册功能逻辑及其实现

BlueBell注册功能逻辑及其实现注册路由 r POST signup controller SignupHandle 控制层实现 第一步 获取参数和参数校验 在 models 包中定义一个注册请求参数的结构体 ParamSignUp 用于将 JSON 参数绑定至结构体中 json 的 tag 用于绑定参数

大家好,我是讯享网,很高兴认识大家。

注册路由

r.POST("/signup", controller.SignupHandler)

讯享网

控制层实现

第一步,获取参数和参数校验

在models包中定义一个注册请求参数的结构体(ParamSignUp),用于将JSON参数绑定至结构体中。

json 的tag用于绑定参数,binding参数是gin内置validator校验的tag,required代表此字段是传入参数中必须要有的,eqfield=xxx,代表此字段与结构体中的xxx字段值需要相等,否则会校验失败,返回错误

讯享网package models // 定义请求的参数结构体 // ParamSignUp 注册请求参数 type ParamSignUp struct { Username string `json:"username" binding:"required"` // 代表校验此字段是必须在的 Password string `json:"password" binding:"required"` RePassword string `json:"re_password" binding:"required,eqfield=Password"` } 

得到一个注册请求参数结构体指针

p := new(models.ParamSignUp) // 得到一个注册请求参数结构体指针

ps:new返回类型的指针。

gin自带ShouldBindJSON方法将传入参数序列化到p结构体中

讯享网 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 { c.JSON(http.StatusOK, gin.H{ "msg": "请求参数错误", }) return } // 如果是就返回翻译过后的内容 c.JSON(http.StatusOK, gin.H{ "msg": errs.Translate(trans), }) return }
Validator翻译器完整代码

由于validator校验返回的错误信息是英文,为方便用户读取,做一个翻译器,将错误类型为validator.ValidationErrors的内容翻译成中文。

package controller /* 用于翻译validator.ValidationErrors错误的内容 */ import ( "bluebell/models" "fmt" "github.com/gin-gonic/gin/binding" "github.com/go-playground/locales/en" "github.com/go-playground/locales/zh" ut "github.com/go-playground/universal-translator" "github.com/go-playground/validator/v10" enTranslations "github.com/go-playground/validator/v10/translations/en" zhTranslations "github.com/go-playground/validator/v10/translations/zh" "reflect" "strings" ) // 定义一个全局翻译器T var trans ut.Translator // InitTrans 初始化翻译器 func InitTrans(locale string) (err error) { // 修改gin框架中的Validator引擎属性,实现自定制 if v, ok := binding.Validator.Engine().(*validator.Validate); ok { // 注册一个获取json tag的自定义方法 v.RegisterTagNameFunc(func(fld reflect.StructField) string { name := strings.SplitN(fld.Tag.Get("json"), ",", 2)[0] if name == "-" { return "" } return name }) // 为SignUpParam注册自定义校验方法 v.RegisterStructValidation(SignUpParamStructLevelValidation, models.ParamSignUp{}) zhT := zh.New() // 中文翻译器 enT := en.New() // 英文翻译器 // 第一个参数是备用(fallback)的语言环境 // 后面的参数是应该支持的语言环境(支持多个) // uni := ut.New(zhT, zhT) 也是可以的 uni := ut.New(enT, zhT, enT) // locale 通常取决于 http 请求头的 'Accept-Language' var ok bool // 也可以使用 uni.FindTranslator(...) 传入多个locale进行查找 trans, ok = uni.GetTranslator(locale) if !ok { return fmt.Errorf("uni.GetTranslator(%s) failed", locale) } // 注册翻译器 switch locale { case "en": err = enTranslations.RegisterDefaultTranslations(v, trans) case "zh": err = zhTranslations.RegisterDefaultTranslations(v, trans) default: err = enTranslations.RegisterDefaultTranslations(v, trans) } return } return } // removeTopStruct 去除提示信息中的结构体名称 func removeTopStruct(fields map[string]string) map[string]string { res := map[string]string{} for field, err := range fields { res[field[strings.Index(field, ".")+1:]] = err } return res } // SignUpParamStructLevelValidation 自定义SignUpParam结构体校验函数 func SignUpParamStructLevelValidation(sl validator.StructLevel) { su := sl.Current().Interface().(models.ParamSignUp) if su.Password != su.RePassword { // 输出错误提示信息,最后一个参数就是传递的param sl.ReportError(su.RePassword, "re_password", "RePassword", "eqfield", "password") } } 

第二步,业务处理,logic层进行业务处理

调用logic包中的Signup方法,实现用户插入数据库的操作,完成注册的功能。

讯享网// 2.业务处理 logic层进行业务处理 if err := logic.Signup(p); err != nil { c.JSON(http.StatusOK, gin.H{ "msg": err.Error(), }) return }
Signup方法实现

第一步,校验用户是否存在

// 1.校验用户是否存在 if err := mysql.CheckUserExist(p); err != nil { return err }

调用mysql中的CheckUserExist方法,判断该用户是否已存在,如果存在,说明该用户已经注册过了。

mysql包中CheckUserExist方法实现
讯享网// CheckUserExist 判断用户是否存在 func CheckUserExist(user *models.ParamSignUp) error { sqlStr := "select count(user_id) from user where username = ?" var count int if err := db.Get(&count, sqlStr, user.Username); err != nil { return err } if count > 0 { return errors.New("用户已存在") } return nil }

搜索相关用户名,统计个数,判断是否大于0,大于0即是存在。


讯享网

第二步,雪花算法生成UID,生成一个用户实例

调用snowflake包中的GenID获取UID

// 2.生成UID UID := snowflake.GenID()

在models表中创建一个用户User结构体,对应数据库中的user表,相互绑定。

讯享网package models /* 构造user结构体与数据库中user表相对应,相互绑定 */ type User struct { UserID int64 `db:"user_id"` UserName string `db:"username"` PassWord string `db:"password"` } 

生成一个用户实例

// 生成一个用户实例 user := &models.User{ UserID: UID, UserName: p.Username, PassWord: p.Password, }

第三步,保存到数据库

调用mysql包中的InsertUser方法,传入用户实例

讯享网// 3.保存到数据库 if err := mysql.InsertUser(user); err != nil { return err }
mysql包中InsertUser方法实现
// InsertUser 向数据库中插入一条用户数据 func InsertUser(user *models.User) error { sqlStr := "insert into user(user_id,username,password) values(?,?,?)" user.PassWord = encryptPassword(user.PassWord) if _, err := db.Exec(sqlStr, user.UserID, user.UserName, user.PassWord); err != nil { return err } return nil } 

创建相关sql语句,执行写入数据库。

mysql包中encryptPassword方法实现

数据库中不能存储明文密码,所以要对密码进行加密。

讯享网// 对密码进行加密 func encryptPassword(oPassword string) string { h := md5.New() h.Write([]byte(secret)) return hex.EncodeToString(h.Sum([]byte(oPassword))) }
 logic/Signup完整代码
package logic import ( "bluebell/dao/mysql" "bluebell/models" "bluebell/pkg/snowflake" ) func Signup(p *models.ParamSignUp) error { // 1.校验用户是否存在 if err := mysql.CheckUserExist(p); err != nil { return err } // 2.生成UID UID := snowflake.GenID() // 生成一个用户实例 user := &models.User{ UserID: UID, UserName: p.Username, PassWord: p.Password, } // 3.保存到数据库 if err := mysql.InsertUser(user); err != nil { return err } return nil }

第三步,返回响应

如果没有任何报错,则返回success

讯享网// 3.返回响应 c.JSON(http.StatusOK, gin.H{ "msg": "success", })

控制层完整代码

package controller import ( "bluebell/logic" "bluebell/models" "github.com/gin-gonic/gin" "github.com/go-playground/validator/v10" "go.uber.org/zap" "net/http" ) 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 { c.JSON(http.StatusOK, gin.H{ "msg": "请求参数错误", }) return } // 如果是就返回翻译过后的内容 c.JSON(http.StatusOK, gin.H{ "msg": errs.Translate(trans), }) return } // 2.业务处理 logic层进行业务处理 if err := logic.Signup(p); err != nil { c.JSON(http.StatusOK, gin.H{ "msg": err.Error(), }) return } // 3.返回响应 c.JSON(http.StatusOK, gin.H{ "msg": "success", }) return } 

小讯
上一篇 2025-02-10 12:11
下一篇 2025-04-11 17:26

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/39832.html