大家好,我是张大鹏,今天又来给大家分享技术文章了。
在之前的文章中,我们已经对Go1.20 + React18 + MySQL 这套前后端分离的权限管理系统做了基本的功能开发,已经实现了登录功能,注销功能等核心功能,这篇文章中,我们来讲一个新增的需求,开发一个获取用户列表的接口。
关于后端的开发,底层框架采用的是大鹏自研的两个框架,zdpgo_api 和 zdpgo_mysql,两个框架都非常的常用,我现在开发新的项目,基本都是基于这两个框架作为底层技术。
关于接口测试,又会用到大鹏自研的另一个框架,zdppy_requests,没错,这是一个Python的框架,整体的开发流程中,咱们会使用Go+Python进行双语言开发,Go写接口,Python写测试。
先来说一下需求:
如图,在咱们之前使用React18开发的过程中,用户列表使用了一个假数据,今天我们来开发一个接口,用于获取真实的用户数据。
整体代码大鹏已经开发完毕了,核心的接口逻辑如下:
func handleGetUserPage(c *zdpgo_api.Context) {
// 校验客户端 Token
if !checkClientToken(c) {
c.ResponseFailureAuth("无效的客户端 Token")
return
}
// 校验登录 Token
_, _, err := checkLoginToken(c)
if err != nil {
log.Printf("解析登录 Token 失败:%s\n", err.Error())
c.ResponseFailureAuth("无效的登录 Token")
return
}
// 获取参数
pageStr := c.DefaultQuery("page", "1")
sizeStr := c.DefaultQuery("size", "20")
page, err := strconv.Atoi(pageStr)
if err != nil {
c.ResponseFailureArgs("查询参数 page 格式不正确 ")
return
}
size, err := strconv.Atoi(sizeStr)
if err != nil {
c.ResponseFailureArgs("查询参数 size 格式不正确 ")
return
}
// 查询总数
count, err := db.UserCount()
if err != nil {
c.ResponseFailure("查询用户总数失败")
return
}
// 查询用户分页数据
users, err := db.UserPage(page, size)
if err != nil {
c.ResponseFailure("查询用户分页数据失败")
return
}
// 返回用户信息
data := &userPage{
Total: count,
Data: users,
}
c.ResponseSuccess(data)
}
这里有一个非常重要的技术细节,那就是如何分页查询用户数据,这里要用到一个非常非常重要的知识点,那就是database/sql这个库中,提供了处理空数据的一些数据结构,比如:
var (
id sql.NullInt32
username sql.NullString
fullname sql.NullString
role sql.NullString
isActive sql.NullBool
gender sql.NullString
age sql.NullInt32
)
err = rows.Scan(&id, &username, &fullname, &role, &isActive, &gender, &age)
if err != nil {
log.Println("提取用户信息失败", err.Error())
return
}
users = append(users, form.User{
Id: int(id.Int32),
Username: username.String,
IsActive: isActive.Bool,
Fullname: fullname.String,
Role: role.String,
Gender: gender.String,
Age: int(age.Int32),
})
在接口开发完毕以后,我们可以使用Python进行测试了,需要模拟一个完整的流程。先登录获取token,然后使用token访问获取用户列表的接口。核心代码如下:
import zdppy_requests as zr
# 先登录
url = "http://localhost:8893/api/v1/auth/login"
headers = {"Authorization": "xxx"}
data = {"username": "zhangdapeng",
"password": "zhangdapeng"}
r = zr.post(url, headers=headers, json=data)
print(r.status_code, r.text)
# 提取登录信息
loginResult = {}
try:
loginResult = r.json()
except Exception as e:
print("登录失败:", e, r.text)
raise e
# 提取 Token
token = loginResult.get("data").get("token")
print("token", loginResult.get("data").get("token"))
# 获取用户分页信息
url = "http://localhost:8893/api/v1/auth/userpage"
headers = {"Authorization": "xxx",
"Zdpgo-Auth-Token": token}
r = zr.get(url, headers=headers)
print(r.status_code, r.text)
这个接口最终返回的数据结构如下:
type userPage struct {
Total int `json:"total"` // 用户名
Data []form.User `json:"data"`
}
这里的form.User的数据结构如下:
type User struct {
Id int `json:"id"`
Username string `json:"username"`
IsActive bool `json:"is_active"`
Fullname string `json:"fullname"`
Role string `json:"role"`
Gender string `json:"gender"`
Age int `json:"age"`
}
谢谢大家~
领取专属 10元无门槛券
私享最新 技术干货