Redis与前端数据类型不匹配导致比较失败的解决方案
使用redigo库操作Redis时,经常遇到Redis返回值与前端值类型不一致的问题,导致比较失败。本文以一个具体案例,分析如何解决[]byte类型Redis返回值与前端字符串值比较不相等的问题。
问题描述:
开发者使用redigo库从Redis获取键为"123@qq.com"的值"8414"。前端通过c.query("code")获取验证码"8414"。直接比较Redis返回的[]byte类型值与前端字符串值,结果总是失败。即使将前端字符串转换为[]byte,比较结果依然错误。根本原因是Redis返回的是字节数组,前端获取的是字符串,两者表示方式不同。Redis返回的字节数组包含字符串的字节表示,可能包含额外字符,例如引号。
原始代码片段:
email := c.query("email") code := c.query("code") str, _ := gredis.get(email) fmt.Println(str, string(str), "", []byte(code+""), code) if string(str) != string(code) { appg.failjson(e.error, "验证码错误") return }
gredis.get函数返回[]byte类型,直接转换为字符串比较导致错误。
改进后的gredis.get函数:
开发者修改了gredis.get函数,加入json.Unmarshal进行解析:
// Get get a key func Get(key string) (interface{}, error) { conn := RedisConn.Get() defer conn.Close() reply, err := redis.Bytes(conn.Do("GET", key)) if err != nil { return nil, err } // 代码1 var reply2 interface{} err = json.Unmarshal(reply, &reply2) if err != nil { return nil, err } return reply2, nil }
通过json.Unmarshal将[]byte类型的Redis返回值解析为interface{}类型,解决了类型不一致的问题,确保后续比较正确。 需要注意的是,这种方法并非所有数据类型都能正确转换,例如存储的结构体数据会被解析为map[string]interface{}类型。
解决方案:
使用json.Unmarshal函数将Redis返回的[]byte数据解析成目标类型。这能将字节数组转换为字符串,避免数据表示方式差异导致的比较错误。 只有数据类型一致,才能保证比较结果正确。 如果存储在Redis中的数据是其他类型(例如数字),则需要根据实际类型进行相应的转换,而不是直接使用json.Unmarshal。 例如,如果存储的是数字,可以使用strconv.Atoi等函数进行转换。