错误码定义如下
╰─➤ cat utils/errmsg/errmsg.go
package errmsg
const (
SUCCESS = 200
ERROR = 500
// code = 1000.. 用户模块的错误
ERROR_USERNAME_USED = 1001
ERROR_PASSWORD_WORNG = 1002
ERROR_USER_NOT_EXIST = 1003
ERROR_TOKEN_EXIST = 1004
ERROR_TOKEN_RUNTIME = 1005
ERROR_TOKEN_WRONG = 1006
ERROR_TOKEN_TYPE = 1007
// code = 2000... 文章模块的错误
// code = 3000... 分类模块的错误
)
var codeMsg = map[int]string{
SUCCESS: "OK",
ERROR: "FAIL",
ERROR_USERNAME_USED: "用户名已存在",
ERROR_PASSWORD_WORNG: "密码错误",
ERROR_USER_NOT_EXIST: "用户不存在",
ERROR_TOKEN_EXIST: "Token不存在",
ERROR_TOKEN_RUNTIME: "Token已过期",
ERROR_TOKEN_WRONG: "Token不正确",
ERROR_TOKEN_TYPE: "Token格式错误",
}
// 输出错误信息返回
func GetErrMsg(code int)string {
return codeMsg[code]
}
在api目录,当前是第一个API大版本,因此在api下新建v1目录,再新建User文件:
╰─➤ cat api/v1/user.go
package v1
import "github.com/gin-gonic/gin"
// 查询用户名是否存在
func UserExist(c *gin.Context) {
}
// 添加用户
func AddUser(c *gin.Context) {
}
// 查询单个用户
// 查询用户列表
func GetUsers(c *gin.Context) {
}
// 编辑用户
func EditUser(c *gin.Context) {
}
// 删除用户
func DeleteUser(c *gin.Context) {
}
注册路由
我们打开routers下的router.go文件,修改文件内容如下
╰─➤ cat routers/router.go
package routers
import (
v1 "ginBlog/api/v1"
"ginBlog/utils"
"github.com/gin-gonic/gin"
)
func InitRouter() {
gin.SetMode(utils.AppMode)
r := gin.Default()
routerV1 := r.Group("api/v1")
{
// 用户模块的路由接口
routerV1.POST("user/add", v1.AddUser)
routerV1.GET("users", v1.GetUsers)
routerV1.PUT("user/:id", v1.EditUser)
routerV1.DELETE("user/:id", v1.DeleteUser)
}
r.Run(utils.HttpPort)
}
命令行,执行go run main.go,检查路由规则是否注册成功
$ go run main.go
编写接口
下载 scrypt ,在后面的接口里会使用到密码加密
go get -u golang.org/x/crypto/scrypt
编写用户列表的model 逻辑,包涵增删改查
model 目录下的user.go
╰─➤ cat model/User.go
package model
import (
"encoding/base64"
"ginBlog/utils/errmsg"
"github.com/jinzhu/gorm"
"golang.org/x/crypto/scrypt"
"log"
)
// 创建User struct{},用于Gorm的使用,并给附属属性json,这样在c.JSON的时候就会自动转换格式
type User struct {
gorm.Model
Username string `gorm:"type:varchar(20);not null" json:"username"`
Password string `gorm:"type:varchar(20);not null" json:"password"`
Role int `gorm:"type:int" json:"role"`
}
// 因为在同个models包下,因此db *gorm.DB是可以直接使用的
// 查询用户是否存在
func CheckUser(name string) (code int) {
var users User
db.Select("id").Where("username = ?", name).First(&users)
if users.ID > 0 {
return errmsg.ERROR_USERNAME_USED //1001
}
return errmsg.SUCCESS
}
// 新增用户
func CreateUser(data *User) int {
// 密码加密
data.Password = ScryptPw(data.Password)
// 写入数据库
err = db.Create(&data).Error
if err != nil {
return errmsg.ERROR
}
return errmsg.SUCCESS
}
// 查询用户列表
func GetUsers(pageSize int, pageNum int) ([]User) {
var users []User
err = db.Limit(pageSize).Offset((pageNum - 1) * pageSize).Find(&users).Error
if err != nil && err != gorm.ErrRecordNotFound {
return nil
}
return users
}
// 编辑用户
func EditUser(id int, data *User) int {
var user User
var maps = make(map[string]interface{})
maps["username"] = data.Username
maps["role"] = data.Role
err = db.Model(&user).Where("id = ?", id).Update(maps).Error
if err != nil {
return errmsg.ERROR
}
return errmsg.SUCCESS
}
// 删除用户
func DeleteUser(id int) int {
var user User
err = db.Where("id = ?", id).Delete(&user).Error
if err != nil {
return errmsg.ERROR
}
return errmsg.SUCCESS
}
// 密码加密
func ScryptPw(password string) string {
const KeyLen = 10
salt := make([]byte, 8)
salt = []byte{12, 32, 4, 6, 66, 22, 222, 11}
HashPw,err := scrypt.Key([]byte(password), salt, 16384, 8, 1, KeyLen)
if err != nil {
log.Fatal(err)
}
fpw := base64.StdEncoding.EncodeToString(HashPw)
return fpw
}
api目录下v1版本的user.go,包涵增删改查
╰─➤ cat api/v1/user.go
package v1
import (
"ginBlog/model"
"ginBlog/utils/errmsg"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
// 新增用户
func AddUser(c *gin.Context) {
var data model.User
// 绑定数据模型
_ = c.ShouldBindJSON(&data)
// 判断用户是否存在,不存在则添加
code := model.CheckUser(data.Username)
if code == errmsg.SUCCESS {
model.CreateUser(&data)
}
if code == errmsg.ERROR_USERNAME_USED {
code = errmsg.ERROR_USERNAME_USED
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": data,
"message": errmsg.GetErrMsg(code),
})
}
// 查询单个用户
// 查询用户列表
func GetUsers(c *gin.Context) {
pageSize,_ := strconv.Atoi(c.Query("pageSize"))
pageNum,_ := strconv.Atoi(c.Query("pageNum"))
// 如果木有传值就不使用分页
if pageSize == 0 {
pageSize = -1
}
if pageNum == 0 {
pageNum = -1
}
data := model.GetUsers(pageSize,pageNum)
code := errmsg.SUCCESS
c.JSON(http.StatusOK, gin.H{
"status": code,
"data": data,
"message": errmsg.GetErrMsg(code),
})
}
// 编辑用户
func EditUser(c *gin.Context) {
var data model.User
id,_ := strconv.Atoi(c.Param("id"))
c.ShouldBindJSON(&data)
code := model.CheckUser(data.Username)
if code == errmsg.SUCCESS {
model.EditUser(id, &data)
}
// 如果用户存在不执行
if code == errmsg.ERROR_USERNAME_USED {
c.Abort()
}
c.JSON(http.StatusOK, gin.H{
"status": code,
"message": errmsg.GetErrMsg(code),
})
}
// 删除用户
func DeleteUser(c *gin.Context) {
id,_ := strconv.Atoi(c.Param("id"))
code := model.DeleteUser(id)
c.JSON(http.StatusOK, gin.H{
"ststus": code,
"message": errmsg.GetErrMsg(code),
})
}