修复db服,login业务逻辑bug,修复反序列化bug
This commit is contained in:
parent
9fdb2df2b6
commit
11cc557518
@ -2,7 +2,6 @@ package model
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"game/common/proto/pb"
|
||||
"game/common/serialization"
|
||||
@ -60,10 +59,13 @@ func (s *TableOp[T]) findByRedis(id uint) *T {
|
||||
if len(maps) == 0 {
|
||||
return nil
|
||||
}
|
||||
jsonByte, _ := json.Marshal(maps)
|
||||
var result resultT[T]
|
||||
_ = json.Unmarshal(jsonByte, &result.ret)
|
||||
log.DebugF("findByRedis redis-key:%v result:%v", s.redisKey(id), result.ret)
|
||||
us, err := serialization.MapStringToStruct[T](maps)
|
||||
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
|
||||
}
|
||||
|
||||
|
21
common/model/tableOperation_test.go
Normal file
21
common/model/tableOperation_test.go
Normal 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)
|
||||
}
|
@ -12,17 +12,17 @@ const (
|
||||
|
||||
// 玩家账户表
|
||||
type UserAccount struct {
|
||||
ID uint `gorm:"primarykey" json:"id,omitempty"`
|
||||
Username string `gorm:"type:varchar(32);uniqueIndex;not null" json:"username,omitempty"` // 用户名
|
||||
Password string `gorm:"type:varchar(255);not null" json:"password,omitempty"` // 密码哈希
|
||||
Email string `gorm:"type:varchar(100)" json:"email,omitempty"` // 邮箱(可选)
|
||||
Phone string `gorm:"type:varchar(20)" json:"phone,omitempty"` // 手机号(可选)
|
||||
DeviceID string `gorm:"type:varchar(64);index" json:"device_id"` // 设备ID
|
||||
LastLoginIP string `gorm:"type:varchar(45)" json:"last_login_ip"` // 最后登录IP(支持IPv6)
|
||||
LastLoginTime time.Time `json:"last_login_time,omitempty"` // 最后登录时间
|
||||
Status int `gorm:"type:tinyint;default:1" json:"status,omitempty"` // 账号状态 1-正常 2-冻结 3-封禁
|
||||
RegisterIP string `gorm:"type:varchar(45)" json:"register_ip,omitempty"` // 注册IP
|
||||
RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP" json:"register_time"` // 注册时间
|
||||
ID uint `gorm:"primarykey" json:"id"`
|
||||
Username string `gorm:"type:varchar(32);uniqueIndex;not null" json:"username"` // 用户名
|
||||
Password string `gorm:"type:varchar(255);not null" json:"password"` // 密码哈希
|
||||
Email string `gorm:"type:varchar(100)" json:"email"` // 邮箱(可选)
|
||||
Phone string `gorm:"type:varchar(20)" json:"phone"` // 手机号(可选)
|
||||
DeviceID string `gorm:"type:varchar(64);index" json:"device_id"` // 设备ID
|
||||
LastLoginIP string `gorm:"type:varchar(45)" json:"last_login_ip"` // 最后登录IP(支持IPv6)
|
||||
LastLoginTime time.Time `json:"last_login_time"` // 最后登录时间
|
||||
Status int `gorm:"type:tinyint;default:1" json:"status"` // 账号状态 1-正常 2-冻结 3-封禁
|
||||
RegisterIP string `gorm:"type:varchar(45)" json:"register_ip"` // 注册IP
|
||||
RegisterTime time.Time `gorm:"type:TIMESTAMP;default:CURRENT_TIMESTAMP" json:"register_time"` // 注册时间
|
||||
}
|
||||
|
||||
func (u UserAccount) GetId() uint {
|
||||
|
@ -1,6 +1,11 @@
|
||||
package serialization
|
||||
|
||||
import "reflect"
|
||||
import (
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"reflect"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
func StructToMap(obj interface{}) map[string]interface{} {
|
||||
out := make(map[string]interface{})
|
||||
@ -19,3 +24,83 @@ func StructToMap(obj interface{}) map[string]interface{} {
|
||||
}
|
||||
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
12
go.mod
@ -12,7 +12,13 @@ require (
|
||||
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 (
|
||||
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-sql-driver/mysql v1.7.0 // 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/gorilla/websocket v1.5.3 // indirect
|
||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||
github.com/jinzhu/now v1.1.5 // 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/nuid v1.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.opentelemetry.io/otel 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/sys v0.33.0 // indirect
|
||||
golang.org/x/text v0.25.0 // indirect
|
||||
@ -54,7 +57,6 @@ require (
|
||||
google.golang.org/grpc v1.62.1 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
gorm.io/driver/mysql v1.5.7 // indirect
|
||||
gorm.io/gorm v1.26.1 // indirect
|
||||
)
|
||||
|
||||
// 关键:指向本地公共库路径[3,5](@ref)
|
||||
|
5
工作.txt
5
工作.txt
@ -7,8 +7,9 @@
|
||||
2.编写db服
|
||||
2.1 login服向db服请求数据及向log db服写入日志。测试rpc机制。(已验证)
|
||||
2.2 db创建表时,主键不会自增,而是随机增加。
|
||||
2.3 首次创建帐号,redis没有写入帐号数据。
|
||||
2.4 第二次登陆,login还会走创建帐号逻辑,导致db服返回重复建号失败。
|
||||
2.3 首次创建帐号,redis没有写入帐号数据。 (已修复)
|
||||
2.4 第二次登陆,login还会走创建帐号逻辑,导致db服返回重复建号失败。 (已修复)
|
||||
2.5 redis写入数据的字段名有误。(已修复)
|
||||
2.5 清理登陆相关调试日志。
|
||||
2.6 login在创建帐号时,还需要创建user。
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user