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

简介: 文章目录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),
  }
}


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


相关文章
|
8月前
|
Linux Go iOS开发
Go语言100个实战案例-进阶与部署篇:使用Go打包生成可执行文件
本文详解Go语言打包与跨平台编译技巧,涵盖`go build`命令、多平台构建、二进制优化及资源嵌入(embed),助你将项目编译为无依赖的独立可执行文件,轻松实现高效分发与部署。
1331 162
|
8月前
|
存储 前端开发 JavaScript
Go语言实战案例-项目实战篇:编写一个轻量级在线聊天室
本文介绍如何用Go语言从零实现一个轻量级在线聊天室,基于WebSocket实现实时通信,支持多人消息广播。涵盖前后端开发、技术选型与功能扩展,助你掌握Go高并发与实时通信核心技术。
886 158
|
9月前
|
数据采集 数据挖掘 测试技术
Go与Python爬虫实战对比:从开发效率到性能瓶颈的深度解析
本文对比了Python与Go在爬虫开发中的特点。Python凭借Scrapy等框架在开发效率和易用性上占优,适合快速开发与中小型项目;而Go凭借高并发和高性能优势,适用于大规模、长期运行的爬虫服务。文章通过代码示例和性能测试,分析了两者在并发能力、错误处理、部署维护等方面的差异,并探讨了未来融合发展的趋势。
933 0
|
9月前
|
数据采集 Go API
Go语言实战案例:使用context控制协程取消
本文详解 Go 语言中 `context` 包的使用,通过实际案例演示如何利用 `context` 控制协程的生命周期,实现任务取消、超时控制及优雅退出,提升并发程序的稳定性与资源管理能力。
487 152
|
9月前
|
负载均衡 监控 Java
微服务稳定性三板斧:熔断、限流与负载均衡全面解析(附 Hystrix-Go 实战代码)
在微服务架构中,高可用与稳定性至关重要。本文详解熔断、限流与负载均衡三大关键技术,结合API网关与Hystrix-Go实战,帮助构建健壮、弹性的微服务系统。
873 1
微服务稳定性三板斧:熔断、限流与负载均衡全面解析(附 Hystrix-Go 实战代码)
|
9月前
|
安全 Go 开发者
Go语言实战案例:使用sync.Mutex实现资源加锁
在Go语言并发编程中,数据共享可能导致竞态条件,使用 `sync.Mutex` 可以有效避免这一问题。本文详细介绍了互斥锁的基本概念、加锁原理及实战应用,通过构建并发安全的计数器演示了加锁与未加锁的区别,并封装了一个线程安全的计数器结构。同时对比了Go中常见的同步机制,帮助开发者理解何时应使用 `Mutex` 及其注意事项。掌握 `Mutex` 是实现高效、安全并发编程的重要基础。
|
9月前
|
数据采集 Go API
Go语言实战案例:多协程并发下载网页内容
本文是《Go语言100个实战案例 · 网络与并发篇》第6篇,讲解如何使用 Goroutine 和 Channel 实现多协程并发抓取网页内容,提升网络请求效率。通过实战掌握高并发编程技巧,构建爬虫、内容聚合器等工具,涵盖 WaitGroup、超时控制、错误处理等核心知识点。
|
7月前
|
存储 安全 Java
【Golang】(4)Go里面的指针如何?函数与方法怎么不一样?带你了解Go不同于其他高级语言的语法
结构体可以存储一组不同类型的数据,是一种符合类型。Go抛弃了类与继承,同时也抛弃了构造方法,刻意弱化了面向对象的功能,Go并非是一个传统OOP的语言,但是Go依旧有着OOP的影子,通过结构体和方法也可以模拟出一个类。
374 2
|
9月前
|
Cloud Native 安全 Java
Go:为云原生而生的高效语言
Go:为云原生而生的高效语言
566 1
|
11月前
|
开发框架 JSON 中间件
Go语言Web开发框架实践:路由、中间件、参数校验
Gin框架以其极简风格、强大路由管理、灵活中间件机制及参数绑定校验系统著称。本文详解其核心功能:1) 路由管理,支持分组与路径参数;2) 中间件机制,实现全局与局部控制;3) 参数绑定,涵盖多种来源;4) 结构体绑定与字段校验,确保数据合法性;5) 自定义校验器扩展功能;6) 统一错误处理提升用户体验。Gin以清晰模块化、流程可控及自动化校验等优势,成为开发者的优选工具。