修复db服,login业务逻辑bug,修复反序列化bug

This commit is contained in:
liuxiaobo 2025-06-04 02:40:13 +08:00
parent 9fdb2df2b6
commit 11cc557518
6 changed files with 134 additions and 23 deletions

View File

@ -2,7 +2,6 @@ package model
import ( import (
"context" "context"
"encoding/json"
"fmt" "fmt"
"game/common/proto/pb" "game/common/proto/pb"
"game/common/serialization" "game/common/serialization"
@ -60,10 +59,13 @@ func (s *TableOp[T]) findByRedis(id uint) *T {
if len(maps) == 0 { if len(maps) == 0 {
return nil return nil
} }
jsonByte, _ := json.Marshal(maps)
var result resultT[T] var result resultT[T]
_ = json.Unmarshal(jsonByte, &result.ret) us, err := serialization.MapStringToStruct[T](maps)
log.DebugF("findByRedis redis-key:%v result:%v", s.redisKey(id), result.ret) if err != nil {
log.ErrorF("serialization map to struct err: %v", err)
return nil
}
log.DebugF("findByRedis redis-key:%v result:%v", s.redisKey(id), us)
return &result.ret return &result.ret
} }

View File

@ -0,0 +1,21 @@
package model
import (
"encoding/json"
"game/common/model/user"
"game/common/serialization"
"testing"
)
func Test_zz(t *testing.T) {
zz := `{\"device_id\":\"\",\"email\":\"\",\"id\":\"17\",\"last_login_ip\":\"114.132.124.145:49486\",\"last_login_time\":\"2025-06-04T02:01:49.72898394+08:00\",\"password\":\"$2a$10$p4GJtWzmhaUcT0i/SNpsWOE6uNq8JzymuB6Lv2Qf0Bpg32YthnWgK\",\"phone\":\"\",\"register_ip\":\"114.132.124.145:49486\",\"register_time\":\"0001-01-01T00:00:00Z\",\"status\":\"1\",\"username\":\"test0001\"}`
us := &user.UserAccount{}
_ = json.Unmarshal([]byte(zz), us)
var err error
us, err = serialization.MapStringToStruct[user.UserAccount](map[string]string{
"id": "17",
})
t.Log(err)
t.Log(us)
}

View File

@ -12,17 +12,17 @@ const (
// 玩家账户表 // 玩家账户表
type UserAccount struct { type UserAccount struct {
ID uint `gorm:"primarykey" json:"id,omitempty"` ID uint `gorm:"primarykey" json:"id"`
Username string `gorm:"type:varchar(32);uniqueIndex;not null" json:"username,omitempty"` // 用户名 Username string `gorm:"type:varchar(32);uniqueIndex;not null" json:"username"` // 用户名
Password string `gorm:"type:varchar(255);not null" json:"password,omitempty"` // 密码哈希 Password string `gorm:"type:varchar(255);not null" json:"password"` // 密码哈希
Email string `gorm:"type:varchar(100)" json:"email,omitempty"` // 邮箱(可选) Email string `gorm:"type:varchar(100)" json:"email"` // 邮箱(可选)
Phone string `gorm:"type:varchar(20)" json:"phone,omitempty"` // 手机号(可选) Phone string `gorm:"type:varchar(20)" json:"phone"` // 手机号(可选)
DeviceID string `gorm:"type:varchar(64);index" json:"device_id"` // 设备ID DeviceID string `gorm:"type:varchar(64);index" json:"device_id"` // 设备ID
LastLoginIP string `gorm:"type:varchar(45)" json:"last_login_ip"` // 最后登录IP(支持IPv6) LastLoginIP string `gorm:"type:varchar(45)" json:"last_login_ip"` // 最后登录IP(支持IPv6)
LastLoginTime time.Time `json:"last_login_time,omitempty"` // 最后登录时间 LastLoginTime time.Time `json:"last_login_time"` // 最后登录时间
Status int `gorm:"type:tinyint;default:1" json:"status,omitempty"` // 账号状态 1-正常 2-冻结 3-封禁 Status int `gorm:"type:tinyint;default:1" json:"status"` // 账号状态 1-正常 2-冻结 3-封禁
RegisterIP string `gorm:"type:varchar(45)" json:"register_ip,omitempty"` // 注册IP RegisterIP string `gorm:"type:varchar(45)" json:"register_ip"` // 注册IP
RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP" json:"register_time"` // 注册时间 RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP" json:"register_time"` // 注册时间
} }
func (u UserAccount) GetId() uint { func (u UserAccount) GetId() uint {

View File

@ -1,6 +1,11 @@
package serialization package serialization
import "reflect" import (
"encoding/json"
"fmt"
"reflect"
"strconv"
)
func StructToMap(obj interface{}) map[string]interface{} { func StructToMap(obj interface{}) map[string]interface{} {
out := make(map[string]interface{}) out := make(map[string]interface{})
@ -19,3 +24,83 @@ func StructToMap(obj interface{}) map[string]interface{} {
} }
return out return out
} }
func keyValueToField(key, value string, fieldValue *reflect.Value) error {
switch fieldValue.Kind() {
case reflect.Int8, reflect.Int, reflect.Int16, reflect.Int32, reflect.Int64:
if v, err := strconv.ParseInt(value, 10, 0); err == nil {
fieldValue.SetInt(v)
} else {
return err
}
case reflect.Uint8, reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64:
if v, err := strconv.ParseUint(value, 10, 0); err == nil {
fieldValue.SetUint(v)
} else {
return err
}
case reflect.Float32, reflect.Float64:
if v, err := strconv.ParseFloat(value, 0); err == nil {
fieldValue.SetFloat(v)
} else {
return err
}
case reflect.String:
fieldValue.SetString(value)
case reflect.Bool:
if v, err := strconv.ParseBool(value); err == nil {
fieldValue.SetBool(v)
} else {
return err
}
default:
nv := reflect.New(fieldValue.Type())
if err := json.Unmarshal([]byte(value), nv.Interface()); err == nil {
if fieldValue.Kind() == nv.Elem().Kind() {
fieldValue.Set(nv.Elem())
} else {
return fmt.Errorf("field:%v should have same type.original type:%v, reflect type:%v", key, fieldValue.Kind().String(), nv.Elem().Kind().String())
}
} else {
return err
}
}
return nil
}
func deserializeMapString(kvs map[string]string, structObj interface{}) error {
val := reflect.ValueOf(structObj).Elem()
typ := val.Type()
for i := 0; i < typ.NumField(); i++ {
field := typ.Field(i)
// 检查字段是否可设置(即导出)
if !field.IsExported() {
continue
}
fieldName := field.Tag.Get("json")
if fieldName == "-" {
continue
}
if value, ok := kvs[fieldName]; ok {
// 获取字段的反射值
fieldValue := val.FieldByName(field.Name)
if err := keyValueToField(field.Tag.Get("json"), value, &fieldValue); err != nil {
return err
}
} else {
return fmt.Errorf("redis:%v not has field:%v ", typ.Name(), field.Tag.Get("json"))
}
}
return nil
}
type resultT[T any] struct {
ret T
}
func MapStringToStruct[T any](maps map[string]string) (*T, error) {
result := &resultT[T]{}
err := deserializeMapString(maps, &result.ret)
return &result.ret, err
}

12
go.mod
View File

@ -12,7 +12,13 @@ require (
go.uber.org/zap v1.27.0 // indirect go.uber.org/zap v1.27.0 // indirect
) )
require google.golang.org/protobuf v1.33.0 require (
github.com/golang/protobuf v1.5.4
github.com/nats-io/nats.go v1.42.0
golang.org/x/crypto v0.38.0
google.golang.org/protobuf v1.33.0
gorm.io/gorm v1.26.1
)
require ( require (
github.com/ClickHouse/ch-go v0.65.1 // indirect github.com/ClickHouse/ch-go v0.65.1 // indirect
@ -26,13 +32,11 @@ require (
github.com/go-faster/errors v0.7.1 // indirect github.com/go-faster/errors v0.7.1 // indirect
github.com/go-sql-driver/mysql v1.7.0 // indirect github.com/go-sql-driver/mysql v1.7.0 // indirect
github.com/gogo/protobuf v1.3.2 // indirect github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.4 // indirect
github.com/google/uuid v1.6.0 // indirect github.com/google/uuid v1.6.0 // indirect
github.com/gorilla/websocket v1.5.3 // indirect github.com/gorilla/websocket v1.5.3 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/klauspost/compress v1.18.0 // indirect github.com/klauspost/compress v1.18.0 // indirect
github.com/nats-io/nats.go v1.42.0 // indirect
github.com/nats-io/nkeys v0.4.11 // indirect github.com/nats-io/nkeys v0.4.11 // indirect
github.com/nats-io/nuid v1.0.1 // indirect github.com/nats-io/nuid v1.0.1 // indirect
github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect github.com/orcaman/concurrent-map/v2 v2.0.1 // indirect
@ -45,7 +49,6 @@ require (
go.etcd.io/etcd/client/v3 v3.5.19 // indirect go.etcd.io/etcd/client/v3 v3.5.19 // indirect
go.opentelemetry.io/otel v1.35.0 // indirect go.opentelemetry.io/otel v1.35.0 // indirect
go.opentelemetry.io/otel/trace v1.35.0 // indirect go.opentelemetry.io/otel/trace v1.35.0 // indirect
golang.org/x/crypto v0.38.0 // indirect
golang.org/x/net v0.40.0 // indirect golang.org/x/net v0.40.0 // indirect
golang.org/x/sys v0.33.0 // indirect golang.org/x/sys v0.33.0 // indirect
golang.org/x/text v0.25.0 // indirect golang.org/x/text v0.25.0 // indirect
@ -54,7 +57,6 @@ require (
google.golang.org/grpc v1.62.1 // indirect google.golang.org/grpc v1.62.1 // indirect
gopkg.in/yaml.v3 v3.0.1 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect
gorm.io/driver/mysql v1.5.7 // indirect gorm.io/driver/mysql v1.5.7 // indirect
gorm.io/gorm v1.26.1 // indirect
) )
// [3,5](@ref) // [3,5](@ref)

View File

@ -7,8 +7,9 @@
2.编写db服 2.编写db服
2.1 login服向db服请求数据及向log db服写入日志。测试rpc机制。(已验证) 2.1 login服向db服请求数据及向log db服写入日志。测试rpc机制。(已验证)
2.2 db创建表时主键不会自增而是随机增加。 2.2 db创建表时主键不会自增而是随机增加。
2.3 首次创建帐号redis没有写入帐号数据。 2.3 首次创建帐号redis没有写入帐号数据。 (已修复)
2.4 第二次登陆login还会走创建帐号逻辑导致db服返回重复建号失败。 2.4 第二次登陆login还会走创建帐号逻辑导致db服返回重复建号失败。 (已修复)
2.5 redis写入数据的字段名有误。(已修复)
2.5 清理登陆相关调试日志。 2.5 清理登陆相关调试日志。
2.6 login在创建帐号时还需要创建user。 2.6 login在创建帐号时还需要创建user。