Go 简易登陆功能:go-redis Hash
我们要实现的功能是通过 Redis 来存储用户信息,但是存储之前我们先要从数据库里拿到这些数据。
我们先假装有一个数据库,因为要简单,所以直接用代码伪装一个数据库。
但是再此之前需要先定义一个 User
类。
type User struct {
Id int64 `json:"id" redis:"id"`
Username string `json:"username" redis:"username"`
Password string `json:"password" redis:"password"`
Email string `json:"email" redis:"email"`
Url string `json:"url" redis:"url"`
}
然后自己假装一个数据库(需要有注册、获取功能):
type YouDB struct {
users map[string]*User
}
func (y *YouDB) Register(user *User) {
y.users[user.Username] = user
}
func (y *YouDB) GetUser(username string) (*User, error) {
user, ok := y.users[username]
if !ok {
return &User{}, errors.New("用户不存在")
}
return user, nil
}
然后因为是测试而已,所以需要自己新建一些用户信息,用上面的 YouDB
类创建一个数据库:
func BeforeDb() *YouDB {
db := &YouDB{
users: make(map[string]*User),
}
db.Register(&User{
Id: 1,
Username: "zhangsan",
Password: "123456",
Email: "123@qq.com",
Url: "https://200011.net",
})
db.Register(&User{
Id: 2,
Username: "lisi",
Password: "321123",
Email: "321@qq.com",
Url: "https://blog.200011.net",
})
return db
}
然后就是 Login
函数了:
func Login(username string, password string) {
// 连接 redis
rdb := connect.Connect()
defer rdb.Close()
// 获取 context
ctx := context.Background()
// 用户 Key 前缀
prefix := "user:"
// 当前待登陆用户的 key
key := prefix + username
// 执行操作
getAll := rdb.HGetAll(ctx, key)
userCache, err := getAll.Result()
user := new(User)
if err == nil {
if len(userCache) == 0 {
// 如果 HGetAll 的结果为空,则用户不在 Redis,需要到数据库读取数据
fmt.Println("用户缓存不在 Redis,开始从数据库读取数据")
// 从数据库读取用户信息
db := BeforeDb()
mUser, err := db.GetUser(username)
if err != nil {
fmt.Printf("登陆失败:%s\n", err.Error())
return
}
user = mUser
// 将 user 使用 Hash 写入 Redis
err = rdb.HSet(ctx, key, user).Err()
if err != nil {
fmt.Printf("登陆失败:%s\n", err.Error())
return
}
fmt.Printf("User: %s, 已写入缓存\n", user.Username)
} else {
// 如果已经存在 Redis 中
fmt.Println("缓存hit")
// 将用户的信息从 Hash 读取到 user
getAll.Scan(user)
}
// 判断密码是否正确
if user.Password == password {
fmt.Println("登陆成功")
} else {
fmt.Println("登陆失败:密码错误")
}
} else {
fmt.Println(err.Error())
}
fmt.Println("=====================================")
}
简单测试一下:
func TestLogin(t *testing.T) {
Login("zhangsan", "123456")
Login("lisi", "123123")
}
输出如下:
代码思路:说透 Redis7:第 9 篇