1、前言
什么是web应用,Web应用程序简单流程如下图所示
通过上图我们发现,我们 GoWeb 实战项目还缺少最后关键的环节数据库。那么如何使用 GO 语言操作数据库并完成增删改查等操作是我们今天学习的目标。
GoWeb 的 MVC 入门实战案例,基于 Iris 框架实现(附案例全代码)
2、什么是ORM
对象关系映射(Object Relational Mapping,简称ORM)是通过使用描述对象和数据库之间映射的元数据,将程序中的对象自动持久化到关系数据库中。
我们是面向对象的。当对象的信息发生变化的时候,我们就需要把对象的信息保存在关系数据库中。程序员会在自己的业务逻辑代码中夹杂很多 SQL 语句用来增加、读取、修改、删除相关数据,而这些代码通常都是重复的。
ORM 的出现充当了对象和数据库层次的桥梁作用。
3、MySQL
3.1、什么是MySQL
MySQL是一个关系型数据库管理系统,由瑞典MySQL AB 公司开发,属于 Oracle 旗下产品。MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Database Management System,关系数据库管理系统) 应用软件之一。
MySQL是一种关系型数据库管理系统,关系数据库将数据保存在不同的表中,而不是将所有数据放在一个大仓库内,这样就增加了速度并提高了灵活性。
MySQL所使用的 SQL 语言是用于访问数据库的最常用标准化语言。MySQL 软件采用了双授权政策,分为社区版和商业版,由于其体积小、速度快、总体拥有成本低,尤其是开放源码这一特点,一般中小型和大型网站的开发都选择 MySQL 作为网站数据库。
3.2、MySQL 安装
3.2.1 Docker 环境
3.2.2 菜鸟教程
3.3、创建数据库
通过 Navicat Premium 快速创建数据库,数据库名示例:go_gorm,字符集选择:utf8mb4,排序规则选择: utf8mb4_general_ci。最后点击确认即可
3.4、创建数据表
创建一张系统用户表,用户完成我们后续的 CRUD 等操作,建表语句如下:
-- ----------------------------
-- 系统用户
-- ----------------------------
DROP TABLE IF EXISTS `sys_user`;
CREATE TABLE `sys_user`
(
`id` bigint unsigned NOT NULL AUTO_INCREMENT COMMENT '主键 ID',
`name` varchar(10) NOT NULL DEFAULT '' COMMENT '用户名',
`account` varchar(20) NOT NULL DEFAULT '' COMMENT '账号',
`password` varchar(64) NOT NULL DEFAULT '' COMMENT '密码',
`password_salt` varchar(64) NOT NULL DEFAULT '' COMMENT '密码盐值',
`mail_address` varchar(64) NOT NULL DEFAULT '' COMMENT '邮箱地址',
`phone_number` varchar(20) NOT NULL DEFAULT '' COMMENT '手机号码',
`age` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '用户年龄',
`is_using` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '是否启用 1是 0否(默认0)',
`is_delete` tinyint unsigned NOT NULL DEFAULT '0' COMMENT '是否删除 1是 0否(默认0)',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',
`update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '修改时间',
`remark` varchar(100) NOT NULL DEFAULT '' COMMENT '描述',
PRIMARY KEY (`id`)
) ENGINE=InnoDB AUTO_INCREMENT=1 DEFAULT CHARSET=utf8mb3 COMMENT='系统用户';
3.5、新增数据
新增一条超级管理员数据。注意:当前用户密码使用明文存储存在安全隐患
INSERT INTO `sys_user` ( `name`, `account`, `password` ) VALUES ('超级管理员', 'admin', '123456')
4、编写代码
此项目根据 《GoWeb 进阶的实战项目,基于 Iris 框架实现 JWT 认证(附案例全代码)》源代码进阶,如果只想了解 CRUD 可以忽略
4.1、安装软件包
# gorm 安装
go get -u gorm.io/gorm
# mysql 驱动
go get -u gorm.io/driver/mysql
4.2、编写代码
4.2.1、加载 MySQL 数据库
在 utils/db 目录新建文件 mysql.go,完整代码如下:
package db
import (
"fmt"
"log"
"os"
"time"
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
)
// 全局变量
var GormDb *gorm.DB
func init() {
fmt.Println("开始加载 MySQL 数据库")
GormDb = InitMysql()
}
/*
* <h2>初始化 MySQL 数据库</h2>
**/
func InitMysql() *gorm.DB {
// GORM 定义了这些日志级别:Silent、Error、Warn、Info
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
logger.Config{
SlowThreshold: time.Second, // 慢 SQL 阈值
LogLevel: logger.Info, // 日志级别
IgnoreRecordNotFoundError: false, // 忽略ErrRecordNotFound(记录未找到)错误
Colorful: false, // 禁用彩色打印
},
)
// MySQL 数据库地址和用户信息
dsn := "替换自己数据库用户名:替换自己数据库密码@tcp(数据库IP地址:数据库端口)/go_gorm?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.New(mysql.Config{
DSN: dsn, // DSN data source name
DefaultStringSize: 256, // string 类型字段的默认长度
DisableDatetimePrecision: true, // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
DontSupportRenameIndex: true, // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
DontSupportRenameColumn: true, // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
SkipInitializeWithVersion: false, // 根据当前 MySQL 版本自动配置
}), &gorm.Config{Logger: newLogger})
if err != nil {
fmt.Println("加载数据库异常信息:", err)
return nil
}
// 获取通用数据库对象 sql.DB,然后使用其提供的功能
mysqlDB, err := db.DB()
if err != nil {
fmt.Println("获取通用数据库对象异常信息:", err)
return nil
}
// Ping
err = mysqlDB.Ping()
if err != nil {
fmt.Println("数据库连接异常信息:", err.Error())
return nil
}
fmt.Println("数据库连接成功", mysqlDB)
// SetMaxIdleConns 用于设置连接池中空闲连接的最大数量。
mysqlDB.SetMaxIdleConns(10)
// SetMaxOpenConns 设置打开数据库连接的最大数量。
mysqlDB.SetMaxOpenConns(100)
// SetConnMaxLifetime 设置了连接可复用的最大时间。
mysqlDB.SetConnMaxLifetime(time.Hour)
return db
}
4.2.2、业务异常自定义
在 utils/constant 目录修改文件 errors.go,完整代码如下:
package constant
import "errors"
/**
* <h1>业务异常自定义</h1>
* Created by woniu
*/
var (
ResErrAuthorizationIsNilErr = errors.New("1001_token 为空")
ResErrSysUserPasswordErr = errors.New("2001_密码错误")
ResErrIdIsNil = errors.New("2002_主键 ID 不能为空")
ResErrSysUserRepeat = errors.New("2003_用户已存在")
ResErrSysUserIsNil = errors.New("2004_用户不存在")
)
4.2.3、系统用户模型
在 app/model 目录新建文件 sys_user.go,完整代码如下:
package model
import "time"
// 系统用户信息
type SysUser struct {
Id int64 `gorm:"primaryKey"` // 用户 ID
Name string `gorm:"column:name"` // 用户姓名
Account string `gorm:"column:account"` // 用户账号
Password string `gorm:"column:password"` // 用户密码
PasswordSalt string `gorm:"column:password_salt"` // 密码盐值
MailAddress string `gorm:"column:mail_address"` // 邮箱地址
PhoneNumber string `gorm:"column:phone_number"` // 手机号码
Age int `gorm:"column:age"` // 用户年龄
IsUsing int `gorm:"column:is_using"` // 是否启用 1是 0否(默认0)
IsDelete int `gorm:"column:is_delete"` // 是否删除 1是 0否(默认0)
CreateTime time.Time `gorm:"column:create_time"` // 创建时间
UpdateTime time.Time `gorm:"column:update_time"` // 修改时间
Remark string `gorm:"column:remark"` // 描述
}
// TableName 指定表名
func (SysUser) TableName() string {
return "sys_user"
}
4.2.4、系统用户响应结构
在 app/vo 目录修改文件 sys_user_vo.go,完整代码如下:
package vo
// 系统用户信息
type SysUserVo struct {
Id int64 `json:"id"` // 用户 ID
Name string `json:"name"` // 用户姓名
Account string `json:"account"` // 用户账号
MailAddress string `json:"mailAddress"` // 邮箱地址
PhoneNumber string `json:"phoneNumber"` // 手机号码
Age int `json:"age"` // 用户年龄
IsUsing int `json:"isUsing"` // 是否启用 1是 0否(默认0)
IsDelete int `json:"isDelete"` // 是否删除 1是 0否(默认0)
CreateTime string `json:"createTime"` // 创建时间
UpdateTime string `json:"updateTime"` // 修改时间
Remark string `json:"remark"` // 描述
Token string `json:"token"` // token
}
4.2.5、分页数据响应结构
注意:此结构体是分页核心
在 app/vo 目录新建文件 page.go,完整代码如下:
package vo
// 分页数据结构
type Page struct {
Current int64 `json:"current"` // 当前页码
Size int64 `json:"size"` // 每页条数
Total int64 `json:"total"` // 总数据量
Pages int64 `json:"pages"` // 总分页数
Records interface{} `json:"records"` // 分页数据
}
/**
* <h2>提供了一个构造方法</h2>
* 需要传入当前页码和每页条数
*/
func NewPage(current, size int64) *Page {
return &Page{Current: current, Size: size}
}
/**
* <h2>设置总数据量</h2>
*/
func (p *Page) SetTotal(t int64) {
p.Total = t
// 总分页数 = 总数据量 / 每页条数
s := p.GetTotal() / p.GetSize()
// 如果总数据量 / 每页条数有余数,则总分页数 + 1
if p.GetTotal()%p.GetSize() != 0 {
s = s + 1
}
p.Pages = s
}
/**
* <h2>设置分页数据</h2>
*/
func (page *Page) SetRecords(records interface{}) {
page.Records = records
}
/**
* <h2>获取当前页码</h2>
* 默认当前页码 1
*/
func (p *Page) GetCurrent() int64 {
if p.Current < 1 {
p.Current = 1
}
return p.Current
}
/**
* <h2>获取数据偏移量</h2>
*/
func (p *Page) GetOffset() int64 {
if p.GetCurrent() > 0 {
return (p.GetCurrent() - 1) * p.GetSize()
}
return 0
}
/**
* <h2>获取每页条数</h2>
* 默认每页 10 条数据
*/
func (p *Page) GetSize() int64 {
if p.Size < 1 {
p.Size = 10
}
return p.Size
}
/**
* <h2>获取总数据量</h2>
*/
func (p *Page) GetTotal() int64 {
return p.Total
}
/**
* <h2>获取总分页数</h2>
*/
func (p *Page) GetPages() int64 {
return p.Pages
}
/**
* <h2>获取分页数据</h2>
*/
func (page *Page) GetRecords() interface{} {
return page.Records
}
4.2.6、系统用户业务处理
注意:此业务处理类本次项目进阶核心代码
- 用户登录校验由固定密码改为数据库动态校验
- 系统用户增加数据
- 系统用户修改数据
- 系统用户删除数据
- 系统用户查询数据
- 系统用户查询数据列表
在 app/service 目录修改文件 sys_user_service.go,完整代码如下:
package service
import (
"fmt"
"go-iris/app/dto"
"go-iris/app/model"
"go-iris/app/vo"
"go-iris/utils/constant"
"go-iris/utils/db"
"go-iris/utils/tool"
)
/**
* <h1>系统用户业务处理</h1>
* Created by woniu
*/
var SysUser = new(sysUserService)
type sysUserService struct{}
/**
* <h2>用户账号 + 用户密码登录</h2>
*/
func (service *sysUserService) PasswordLogin(account string, password string) (*vo.SysUserVo, error) {
// 用户账号为空
if tool.IsEmpty(account) {
return nil, constant.ResErrSysUserIsNil
}
// 用户密码为空
if tool.IsEmpty(password) {
return nil, constant.ResErrSysUserPasswordErr
}
// 根据用户账号查询用户信息
sysUser := service.GetSysUserByAccount(account)
if sysUser == nil {
return nil, constant.ResErrSysUserIsNil
}
// 密码不匹配(暂时使用明文密码比对)
if password != sysUser.Password {
return nil, constant.ResErrSysUserPasswordErr
}
// 用户名 + 密码 校验正确,返回用户信息
return service.GetSysUserVo(sysUser), nil
}
/**
* <h2>根据用户账号查询用户信息</h2>
*/
func (service *sysUserService) GetSysUserByAccount(account string) *model.SysUser {
var sysUser = &model.SysUser{}
// 根据用户账号查询一条数据,主键 ID 排序
result := db.GormDb.Table(sysUser.TableName()).Where("account = ?", account).First(sysUser)
// 查询不到记录报错
if result.Error != nil {
fmt.Println("数据查询异常:", result.Error)
return nil
}
return sysUser
}
/**
* <h2>新增系统用户</h2>
*/
func (service *sysUserService) Save(sysUser model.SysUser) (*vo.SysUserVo, error) {
// 根据用户账号查询用户信息
sysUserOld := service.GetSysUserByAccount(sysUser.Account)
if sysUserOld != nil {
return nil, constant.ResErrSysUserRepeat
}
// 主键采用数据库自增
sysUser.Id = 0
// 创建时间
sysUser.CreateTime = tool.DataTimeNow()
// 修改时间
sysUser.UpdateTime = sysUser.CreateTime
// 创建记录
result := db.GormDb.Table(sysUser.TableName()).Create(&sysUser)
// 返回 error
if result.Error != nil {
fmt.Println("数据新增异常:", result.Error)
return nil, result.Error
}
fmt.Println("数据新增成功,主键ID:", sysUser.Id)
return service.GetSysUserVo(&sysUser), nil
}
/**
* <h2>根据主键 ID 修改用户</h2>
*/
func (service *sysUserService) UpdateById(sysUser model.SysUser) (*model.SysUser, error) {
if sysUser.Id < 1 {
return nil, constant.ResErrIdIsNil
}
// 如果修改用户账号,则需要判断账号是否重复
if tool.IsNotEmpty(sysUser.Account) {
// 根据用户账号查询用户信息
sysUserOld := service.GetSysUserByAccount(sysUser.Account)
// 如果用户账号存在并且ID不相等
if sysUserOld != nil && sysUserOld.Id != sysUser.Id {
return nil, constant.ResErrSysUserRepeat
}
}
// 修改时间
sysUser.UpdateTime = tool.DataTimeNow()
// Updates 方法支持 struct 和 map[string]interface{} 参数。
// 当使用 struct 更新时,默认情况下,GORM 只会更新非零值的字段
result := db.GormDb.Table(sysUser.TableName()).Model(&sysUser).Updates(&sysUser)
// 返回 error
if result.Error != nil {
fmt.Println("数据修改异常:", result.Error)
return nil, result.Error
}
return service.GetById(sysUser)
}
/**
* <h2>根据主键 ID 查询用户</h2>
*/
func (service *sysUserService) GetById(sysUser model.SysUser) (*model.SysUser, error) {
if sysUser.Id < 1 {
return nil, constant.ResErrIdIsNil
}
// 当目标对象有一个主要值时,将使用主键构建条件
result := db.GormDb.Table(sysUser.TableName()).First(&sysUser)
// 返回 error
if result.Error != nil {
fmt.Println("数据修改异常:", result.Error)
return nil, result.Error
}
return &sysUser, nil
}
/**
* <h2>根据主键 ID 删除用户</h2>
*/
func (service *sysUserService) RemoveById(sysUser model.SysUser) error {
if sysUser.Id < 1 {
return constant.ResErrIdIsNil
}
// 删除一条记录时,删除对象需要指定主键,否则会触发 批量 Delete
result := db.GormDb.Table(sysUser.TableName()).Delete(&sysUser)
// 返回 error
if result.Error != nil {
fmt.Println("数据删除异常:", result.Error)
return result.Error
}
return nil
}
/**
* <h2>检索全部对象</h2>
*/
func (service *sysUserService) List(sysUser model.SysUser) ([]*vo.SysUserVo, error) {
var sysUserList []model.SysUser
// 检索全部对象
result := db.GormDb.Table(sysUser.TableName()).Find(&sysUserList)
// 返回 error
if result.Error != nil {
fmt.Println("数据列表查询异常:", result.Error)
return nil, result.Error
}
return service.GetSysUserVoList(sysUserList), nil
}
/**
* <h2>检索全部对象 - 分页查询</h2>
*/
func (service *sysUserService) Page(current int64, size int64, sysUserDto dto.SysUserDto) (*vo.Page, error) {
page := vo.NewPage(current, size)
var sysUserList []model.SysUser
var sysUser model.SysUser
query := db.GormDb.Table(sysUser.TableName())
var count int64 // 统计总的记录数
query.Count(&count)
if count > 0 {
result := query.Limit(int(page.GetSize())).Offset(int(page.GetOffset())).Find(&sysUserList)
// 返回 error
if result.Error != nil {
fmt.Println("数据分页查询异常:", result.Error)
return nil, result.Error
}
}
page.SetTotal(count)
page.SetRecords(sysUserList)
fmt.Println(page.GetRecords())
return page, nil
}
/**
* <h2>将 SysUser 集合 转换为 SysUserVo 集合</h2>
*/
func (service *sysUserService) GetSysUserVoList(sysUserList []model.SysUser) []*vo.SysUserVo {
var sysUserVoList []*vo.SysUserVo
for i := range sysUserList {
// 将 SysUser 转换为 SysUserVo
vo := service.GetSysUserVo(&sysUserList[i])
sysUserVoList = append(sysUserVoList, vo)
}
return sysUserVoList
}
/**
* <h2>将 SysUser 转换为 SysUserVo</h2>
*/
func (service *sysUserService) GetSysUserVo(sysUser *model.SysUser) *vo.SysUserVo {
var sysUserVo = vo.SysUserVo{
Id: sysUser.Id,
Name: sysUser.Name,
Account: sysUser.Account,
MailAddress: sysUser.MailAddress,
PhoneNumber: sysUser.PhoneNumber,
Age: sysUser.Age,
IsUsing: sysUser.IsUsing,
IsDelete: sysUser.IsDelete,
CreateTime: tool.DataTimeFormat(sysUser.CreateTime),
UpdateTime: tool.DataTimeFormat(sysUser.UpdateTime),
Remark: sysUser.Remark,
}
return &sysUserVo
}
4.2.7、系统用户控制器
在 app/controller 目录修改文件 sys_user_controller.go,完整代码如下:
package controller
import (
"fmt"
"go-iris/app/dto"
"go-iris/app/model"
"go-iris/app/service"
"go-iris/utils/common"
"go-iris/utils/tool"
"github.com/kataras/iris/v12"
)
/**
* <h1>系统用户控制器</h1>
* Created by woniu
*/
var SysUser = new(SysUserController)
type SysUserController struct{}
/**
* <h2>用户名密码登录</h2>
*/
func (sc *SysUserController) PasswordLogin(ctx iris.Context) {
// 登录参数
var requestModel dto.LoginDto
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
// 用户登录,用户账号 + 用户密码登录
sysUser, err := service.SysUser.PasswordLogin(requestModel.Account, requestModel.Password)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 生成 JWT 的 Token
sysUser.Token = tool.SignedJwtTokenBySysUser(sysUser)
// 响应成功
ctx.JSON(common.ResponseSuccess(sysUser))
}
/**
* <h2>新增用户</h2>
*/
func (sc *SysUserController) Save(ctx iris.Context) {
// 参数
var requestModel model.SysUser
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
// 新增系统用户
_, err := service.SysUser.Save(requestModel)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 响应成功
ctx.JSON(common.ResponseSuccess(nil))
}
/**
* <h2>根据主键 ID 修改用户</h2>
*/
func (sc *SysUserController) UpdateById(ctx iris.Context) {
// 参数
var requestModel model.SysUser
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
// 根据主键 ID 修改用户
_, err := service.SysUser.UpdateById(requestModel)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 响应成功
ctx.JSON(common.ResponseSuccess(nil))
}
/**
* <h2>根据主键 ID 查询用户</h2>
*/
func (sc *SysUserController) GetById(ctx iris.Context) {
// 参数
var requestModel model.SysUser
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
// 根据主键 ID 查询用户
sysUser, err := service.SysUser.GetById(requestModel)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 响应成功
ctx.JSON(common.ResponseSuccess(sysUser))
}
/**
* <h2>根据主键 ID 删除用户</h2>
*/
func (sc *SysUserController) RemoveById(ctx iris.Context) {
// 参数
var requestModel model.SysUser
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
// 根据主键 ID 删除用户
err := service.SysUser.RemoveById(requestModel)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 响应成功
ctx.JSON(common.ResponseSuccess(nil))
}
/**
* <h2>条件查询系统用户列表</h2>
*/
func (sc *SysUserController) List(ctx iris.Context) {
// 参数
var requestModel model.SysUser
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
// 检索全部对象
sysUser, err := service.SysUser.List(requestModel)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 响应成功
ctx.JSON(common.ResponseSuccess(sysUser))
}
/**
* <h2>条件查询系统用户列表</h2>
*/
func (sc *SysUserController) Page(ctx iris.Context) {
// 参数
var requestModel dto.SysUserDto
// 参数绑定
if err := ctx.ReadForm(&requestModel); err != nil {
ctx.JSON(common.ResponseError(-1, "传参异常"))
return
}
fmt.Println("requestModel = ", requestModel)
// 检索全部对象 - 分页查询
page, err := service.SysUser.Page(requestModel.Current, requestModel.Size, requestModel)
if err != nil {
// 响应失败
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 响应成功
ctx.JSON(common.ResponseSuccess(page))
}
4.2.8、请求路由
在 router 目录新建文件 router.go,完整代码如下:
package router
import (
// 自己业务 controller 路径
"fmt"
"go-iris/app/controller"
"go-iris/utils/common"
"go-iris/utils/constant"
"go-iris/utils/tool"
"github.com/kataras/iris/v12"
)
/**
* <h2>注册路由</h2>
*/
func RegisterRouter(app *iris.Application) {
// 跨域解决方案
app.Use(Cors)
// 登录验证中间件
app.Use(CheckAuthorization)
// 系统用户
login := app.Party("/sysUser")
{
// 用户名 + 密码登录
login.Post("/passwordLogin", controller.SysUser.PasswordLogin)
// 新增用户
login.Post("/save", controller.SysUser.Save)
// 根据主键 ID 修改用户
login.Post("/updateById", controller.SysUser.UpdateById)
// 根据主键 ID 查询用户
login.Post("/getById", controller.SysUser.GetById)
// 根据主键 ID 删除用户
login.Post("/removeById", controller.SysUser.RemoveById)
// 条件查询系统用户列表
login.Post("/list", controller.SysUser.List)
// 条件查询系统用户列表 - 分页
login.Post("/page", controller.SysUser.Page)
}
// 通用异常
err := app.Party("/error")
{
err.Get("/responseError", controller.Error.ResponseError)
err.Get("/responseErrorCode", controller.Error.ResponseErrorCode)
err.Get("/responseErrorMessage", controller.Error.ResponseErrorMessage)
}
}
/**
* <h2>跨域解决方案</h2>
*/
func Cors(ctx iris.Context) {
ctx.Header("Access-Control-Allow-Origin", "*")
if ctx.Request().Method == "OPTIONS" {
ctx.Header("Access-Control-Allow-Methods", "GET,POST,PUT,DELETE,PATCH,OPTIONS")
ctx.Header("Access-Control-Allow-Headers", "Content-Type, Accept, Authorization")
ctx.StatusCode(204)
return
}
ctx.Next()
}
/**
* <h2>登录验证中间件</h2>
*/
func CheckAuthorization(ctx iris.Context) {
fmt.Println("登录验证中间件", ctx.Path())
// 放行设置
urlItem := []string{"/sysUser/passwordLogin", "/sysUser/login"}
if !tool.IsStringInArray(ctx.Path(), urlItem) {
// 从请求头中获取Token
token := ctx.GetHeader("Authorization")
// 请求头 Authorization 为空
if tool.IsEmpty(token) {
ctx.JSON(common.ResponseErrorMessage(constant.ResErrAuthorizationIsNilErr.Error()))
return
}
claims, err := tool.ParseWithClaims(token)
if err != nil {
fmt.Println("token 解析异常信息:", err)
ctx.JSON(common.ResponseErrorMessage(err.Error()))
return
}
// 打印消息
claims.ToString()
}
// 前置中间件
ctx.Application().Logger().Infof("Runs before %s", ctx.Path())
ctx.Next()
}
相关代码已完成编写,最终项目结构及文件如下图
5、启动并测试
5.1、启动项目
在 VS Code 终端输入以下命令并执行
# 启动项目
go run main.go
有以下信息代表启动成功
Iris Version: 12.2.0-beta6
Now listening on: http://localhost:8080
Application started. Press CTRL+C to shut down.
5.2、测试接口
5.2.1、用户登录
注意:需要确保系统用户表存在一条初始化数据,没有数据会提示用户不存在
account = admin 并且 password = 123456,响应成功
5.2.2、新增数据
注意:请求头添加 Authorization
5.2.3、主键 ID 修改
注意:请求头添加 Authorization
5.2.4、主键 ID 查询
注意:请求头添加 Authorization
5.2.5、查询数据列表
注意:请求头添加 Authorization
响应结果数据示例如下:
{
"code": 0,
"message": "操作成功",
"data": [
{
"id": 1,
"name": "超级管理员",
"account": "admin",
"mailAddress": "",
"phoneNumber": "",
"age": 0,
"isUsing": 0,
"isDelete": 0,
"createTime": "2022-12-12 17:54:39",
"updateTime": "2022-12-12 17:54:39",
"remark": "",
"token": ""
},
{
"id": 2,
"name": "测试用户名称-修改后",
"account": "test",
"mailAddress": "xxx@163.com",
"phoneNumber": "158XXXXXXXX",
"age": 18,
"isUsing": 0,
"isDelete": 0,
"createTime": "2022-12-12 17:59:59",
"updateTime": "2022-12-12 18:15:35",
"remark": "我是通过接口创建的-修改后",
"token": ""
}
]
}
5.2.6、分页查询
注意:请求头添加 Authorization
响应结果数据示例如下:
{
"code": 0,
"message": "操作成功",
"data": {
"current": 1,
"size": 1,
"total": 2,
"pages": 2,
"records": [
{
"Id": 1,
"Name": "超级管理员",
"Account": "admin",
"Password": "123456",
"PasswordSalt": "",
"MailAddress": "",
"PhoneNumber": "",
"Age": 0,
"IsUsing": 0,
"IsDelete": 0,
"CreateTime": "2022-12-12T17:54:39+08:00",
"UpdateTime": "2022-12-12T17:54:39+08:00",
"Remark": ""
}
]
}
}
5.2.7、主键 ID 删除
注意:请求头添加 Authorization
通过上述测试验证,项目达到预期目标,小伙伴自己赶紧动手试试吧。
6、每日一记
GO 的 ORM框架有那些?哪个才是最优雅的Go ORM 框架?
6.1、GORM
Golang 的出色 ORM 库旨在对开发人员友好。
6.1.1、Github
6.1.2、文档
6.1.3、安装
# gorm 安装
go get -u gorm.io/gorm
# mysql 驱动
go get -u gorm.io/driver/mysql
6.2、XORM
xorm 是一个简单而强大的 Go 语言 ORM 库. 通过它可以使数据库操作非常简便。
6.2.1、Github
6.2.2、文档
6.2.3、安装
# xorm 安装
go get -u github.com/go-xorm/xorm
# mysql 驱动
go get -u github.com/go-sql-driver/mysql
6.3、Ent
ent 是一个简单而又功能强大的 Go 语言实体框架,ent 易于构建和维护应用程序与大数据模型。
6.3.1、Github
6.3.2、文档
6.2.3、安装
# ent 安装
go get -u entgo.io/ent/cmd/ent@latest
6.4、其他
还有其他一些ORM框架,例如:gorose、upper/db 等等。
6.5、如何选择?
没有最好的只有比较合适的,自己根据实际需求按需选择即可。
本文教程到此结束,有问题欢迎大家讨论。
实践是检验真理的唯一标准,一键送三连关注不迷路。
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。
文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/78001.html