【Go实战 | 电商平台】(4) 用户注册

本文涉及的产品
密钥管理服务KMS,1000个密钥,100个凭据,1个月
简介: 文章目录1. 编写路由2. 注册路由3. 注册接口3.1 service层3.2 api层3.2 serializer4. 注册服务用到的包

文章目录

1. 编写路由

2. 注册路由

3. 注册接口

3.1 service层

3.2 api层

3.2 serializer

4. 注册服务

用到的包


github.com/gin-contrib/sessions


github.com/gin-contrib/sessions/cookie


github.com/gin-gonic/gin


1. 编写路由

新建一个WSGI应用程序实例。

r := gin.Default()


设置全局变量store

store := cookie.NewStore([]byte("something-very-secret"))

在路由中使用中间件调用store

r.Use(sessions.Sessions("mysession", store))


2. 注册路由

分一个基础路由组

v1 := r.Group("api/v1")


在这个基础路由编写用户注册路由

v1 := r.Group("api/v1")
{
  //用户操作
  v1.POST("user/register", api.UserRegister)
}

3.1 service层

在service先创建一个user.go

image.png


再在service层上编写用户注册服务的结构体

//UserRegisterService 管理用户注册服务
type UserRegisterService struct {
  Nickname  string `form:"nickname" json:"nickname" binding:"required,min=2,max=10"`
  UserName  string `form:"user_name" json:"user_name" binding:"required,min=5,max=15"`
  Password  string `form:"password" json:"password" binding:"required,min=8,max=16"`
}

在service上编写用户注册register方法

image.png

func (service *UserRegisterService) Register() {
}


3.2 api层

在api层创建user.go

image.png


申请一个 UserRegisterService用户注册服务对象。

var userRegisterService service.UserRegisterService


但是这个服务我们还没有写,先把这个接口写完,再把这个服务补上。


上下文绑定数据

c.ShouldBind(&userRegisterService)

调用这个服务的register方法

res := userRegisterService.Register()


返回这个服务的处理结果

c.JSON(200, res)


api 层的用户注册服务全部代码

func UserRegister(c *gin.Context) {
  var userRegisterService service.UserRegisterService 
  //相当于创建了一个UserRegisterService对象
  if err := c.ShouldBind(&userRegisterService); err == nil {
  res := userRegisterService.Register()
  //调用这个对象中的Register方法。
  c.JSON(200, res)
  } else {
  c.JSON(200, ErrorResponse(err))
  logging.Info(err)
  }
}


创建一个common.go文件, 进行错误的返回

image.png

//返回错误信息 ErrorResponse
func ErrorResponse(err error) serializer.Response {
  if ve, ok := err.(validator.ValidationErrors); ok {
  for _, e := range ve {
    field := conf.T(fmt.Sprintf("Field.%s", e.Field))
    tag := conf.T(fmt.Sprintf("Tag.Valid.%s", e.Tag))
    return serializer.Response{
    Status: 40001,
    Msg:    fmt.Sprintf("%s%s", field, tag),
    Error:  fmt.Sprint(err),
    }
  }
  }
  if _, ok := err.(*json.UnmarshalTypeError); ok {
  return serializer.Response{
    Status: 40001,
    Msg:    "JSON类型不匹配",
    Error:  fmt.Sprint(err),
  }
  }
  return serializer.Response{
  Status: 40001,
  Msg:    "参数错误",
  Error:  fmt.Sprint(err),
  }
}


3.2 serializer

创建一个基础的序列化返回结构体

// Response 基础序列化器
type Response struct {
  Status int         `json:"status"`
  Data   interface{} `json:"data"`
  Msg    string      `json:"msg"`
  Error  string      `json:"error"`
}


image.png


4. 注册服务

接下来我们就可以编写register()注册服务了


先对传过来的用户名进行验证,查看是否已经存在了

model.DB.Model(&model.User{}).Where("user_name=?",service.UserName).Count(&count)
  if count == 1 {
  code = e.ErrorExistUser
  return serializer.Response{
    Status: code,
    Msg:    e.GetMsg(code),
  }
  }


再对密码进行加密

if err := user.SetPassword(service.Password); err != nil {
  logging.Info(err)
  code = e.ErrorFailEncryption
  return serializer.Response{
    Status: code,
    Msg:    e.GetMsg(code),
  }
  }


注意: 我们可以直接再model/user.go下编写密码加密方法

const (
  PassWordCost        = 12         //密码加密难度
  Active       string = "active"   //激活用户
)
//SetPassword 设置密码
func (user *User) SetPassword(password string) error {
  bytes, err := bcrypt.GenerateFromPassword([]byte(password), PassWordCost)
  if err != nil {
  return err
  }
  user.PasswordDigest = string(bytes)
  return nil
}


确认无误之后对用户进行创建

if err := model.DB.Create(&user).Error; err != nil {
  logging.Info(err)
  code = e.ErrorDatabase
  return serializer.Response{
    Status: code,
    Msg:    e.GetMsg(code),
  }
  }

服务层中用户注册的完整代码

func (service *UserRegisterService) Register() serializer.Response {
  var user model.User
  var count int
  code := e.SUCCESS
  model.DB.Model(&model.User{}).Where("user_name=?",service.UserName).Count(&count)
  if count == 1 {
  code = e.ErrorExistUser
  return serializer.Response{
    Status: code,
    Msg:    e.GetMsg(code),
  }
  }
  user = model.User{
  Nickname: service.Nickname,
  UserName: service.UserName,
  Status:   model.Active,
  }
  //加密密码
  if err := user.SetPassword(service.Password); err != nil {
  logging.Info(err)
  code = e.ErrorFailEncryption
  return serializer.Response{
    Status: code,
    Msg:    e.GetMsg(code),
  }
  }
  user.Avatar = "http://q1.qlogo.cn/g?b=qq&nk=294350394&s=640"
  //创建用户
  if err := model.DB.Create(&user).Error; err != nil {
  logging.Info(err)
  code = e.ErrorDatabase
  return serializer.Response{
    Status: code,
    Msg:    e.GetMsg(code),
  }
  }
  return serializer.Response{
  Status: code,
  Msg:    e.GetMsg(code),
  }
}


下一章中,我们编写用户登录的业务逻辑。


相关文章
|
14天前
|
安全 大数据 Go
深入探索Go语言并发编程:Goroutines与Channels的实战应用
在当今高性能、高并发的应用需求下,Go语言以其独特的并发模型——Goroutines和Channels,成为了众多开发者眼中的璀璨明星。本文不仅阐述了Goroutines作为轻量级线程的优势,还深入剖析了Channels作为Goroutines间通信的桥梁,如何优雅地解决并发编程中的复杂问题。通过实战案例,我们将展示如何利用这些特性构建高效、可扩展的并发系统,同时探讨并发编程中常见的陷阱与最佳实践,为读者打开Go语言并发编程的广阔视野。
|
1天前
|
Shell Go API
Go语言grequests库并发请求的实战案例
Go语言grequests库并发请求的实战案例
|
25天前
|
消息中间件 缓存 Kafka
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
go-zero微服务实战系列(八、如何处理每秒上万次的下单请求)
|
25天前
|
缓存 NoSQL Redis
go-zero微服务实战系列(七、请求量这么高该如何优化)
go-zero微服务实战系列(七、请求量这么高该如何优化)
|
24天前
|
消息中间件 SQL 关系型数据库
go-zero微服务实战系列(十、分布式事务如何实现)
go-zero微服务实战系列(十、分布式事务如何实现)
|
24天前
|
消息中间件 NoSQL Kafka
go-zero微服务实战系列(九、极致优化秒杀性能)
go-zero微服务实战系列(九、极致优化秒杀性能)
|
25天前
|
消息中间件 缓存 监控
go-zero微服务实战系列(六、缓存一致性保证)
go-zero微服务实战系列(六、缓存一致性保证)
|
10天前
|
程序员 Go PHP
为什么大部分的 PHP 程序员转不了 Go 语言?
【9月更文挑战第8天】大部分 PHP 程序员难以转向 Go 语言,主要因为:一、编程习惯与思维方式差异,如语法风格和编程范式;二、学习成本高,需掌握新知识体系且面临项目压力;三、职业发展考量,现有技能价值及市场需求不确定性。学习新语言虽有挑战,但对拓宽职业道路至关重要。
40 10
|
8天前
|
Go API 开发者
深入探讨:使用Go语言构建高性能RESTful API服务
在本文中,我们将探索Go语言在构建高效、可靠的RESTful API服务中的独特优势。通过实际案例分析,我们将展示Go如何通过其并发模型、简洁的语法和内置的http包,成为现代后端服务开发的有力工具。
|
10天前
|
算法 程序员 Go
PHP 程序员学会了 Go 语言就能唬住面试官吗?
【9月更文挑战第8天】学会Go语言可提升PHP程序员的面试印象,但不足以 solely “唬住” 面试官。学习新语言能展现学习能力、拓宽技术视野,并增加就业机会。然而,实际项目经验、深入理解语言特性和综合能力更为关键。全面展示这些方面才能真正提升面试成功率。
34 10