英文:
Golang serialize and deserialize back
问题
在Golang中,将结构体序列化和反序列化为字符串的最佳方法(完整性和性能)是什么?
例如,如果我有以下结构体:
type Session struct {
Properties map[string]interface{}
Permissions []int64
}
我想将其存储在Redis中并取回。我已经尝试保存整数和字符串,这是可以的,但如何存储结构体对象呢?
conn := redisConnectors.Get()
// 设置示例
_, err := conn.Do(`SETEX`, `uid_key`, EXPIRE_SEC, user_id)
_, err = conn.Do(`SETEX`, `email_key`, EXPIRE_SEC, login_email)
// 获取示例
user_id, err := redis.Int64(conn.Do(`GET`, `uid_key`))
login_email, err := redis.String(conn.Do(`GET`, `email_key`))
你可以使用Golang的encoding/json
包来将结构体序列化为字符串,然后再反序列化回结构体。这是一个示例代码:
import (
"encoding/json"
"github.com/garyburd/redigo/redis"
)
type Session struct {
Properties map[string]interface{}
Permissions []int64
}
// 序列化结构体为字符串
func serialize(session Session) (string, error) {
data, err := json.Marshal(session)
if err != nil {
return "", err
}
return string(data), nil
}
// 反序列化字符串为结构体
func deserialize(data string) (Session, error) {
var session Session
err := json.Unmarshal([]byte(data), &session)
if err != nil {
return Session{}, err
}
return session, nil
}
// 示例用法
session := Session{
Properties: map[string]interface{}{
"key1": "value1",
"key2": 123,
},
Permissions: []int64{1, 2, 3},
}
// 序列化为字符串
serialized, err := serialize(session)
if err != nil {
// 处理错误
}
// 存储到Redis
_, err = conn.Do(`SETEX`, `session_key`, EXPIRE_SEC, serialized)
if err != nil {
// 处理错误
}
// 从Redis获取
serialized, err := redis.String(conn.Do(`GET`, `session_key`))
if err != nil {
// 处理错误
}
// 反序列化为结构体
deserialized, err := deserialize(serialized)
if err != nil {
// 处理错误
}
这样,你就可以将结构体序列化为字符串并存储在Redis中,然后再从Redis中获取字符串并反序列化回结构体。
英文:
What's the best way (completeness and performance) in Golang to serialize and deserialize a struct to string and vice versa?
for example, if I have this struct:
struct Session {
Properties map[string]interface{}
Permissions []int64
}
I want to store it on Redis and fetch it back. I have tried to save, int and string, it's fine, but how to store struct object?
conn := redisConnectors.Get()
// set example
_, err := conn.Do(`SETEX`, `uid_key`, EXPIRE_SEC, user_id)
_, err = conn.Do(`SETEX`, `email_key`, EXPIRE_SEC, login_email)
// get example
user_id, err := redis.Int64(conn.Do(`GET`, `uid_key`))
login_email, err := redis.String(conn.Do(`GET`, `email_key`))
答案1
得分: 43
import (
"encoding/base64"
"encoding/gob"
"bytes"
)
type SX map[string]interface{}
// go二进制编码器
func ToGOB64(m SX) string {
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(m)
if err != nil { fmt.Println(`failed gob Encode`, err) }
return base64.StdEncoding.EncodeToString(b.Bytes())
}
// go二进制解码器
func FromGOB64(str string) SX {
m := SX{}
by, err := base64.StdEncoding.DecodeString(str)
if err != nil { fmt.Println(`failed base64 Decode`, err); }
b := bytes.Buffer{}
b.Write(by)
d := gob.NewDecoder(&b)
err = d.Decode(&m)
if err != nil { fmt.Println(`failed gob Decode`, err) }
return m
}
当你需要序列化自定义的结构体或类型(例如Session
结构体)时,只需添加以下代码:
func init() {
gob.Register(SX{})
gob.Register(Session{})
}
如果你想使用其他序列化格式(2020年)或者这个基准测试(2022年)来处理动态结构。
英文:
Using gob and base64 could solve the problem, for example:
import (
"encoding/base64"
"encoding/gob"
"bytes"
)
type SX map[string]interface{}
// go binary encoder
func ToGOB64(m SX) string {
b := bytes.Buffer{}
e := gob.NewEncoder(&b)
err := e.Encode(m)
if err != nil { fmt.Println(`failed gob Encode`, err) }
return base64.StdEncoding.EncodeToString(b.Bytes())
}
// go binary decoder
func FromGOB64(str string) SX {
m := SX{}
by, err := base64.StdEncoding.DecodeString(str)
if err != nil { fmt.Println(`failed base64 Decode`, err); }
b := bytes.Buffer{}
b.Write(by)
d := gob.NewDecoder(&b)
err = d.Decode(&m)
if err != nil { fmt.Println(`failed gob Decode`, err); }
return m
}
and when you need to serialize custom struct or type (for example Session
struct), just add these lines:
func init() {
gob.Register(SX{})
gob.Register(Session{})
}
if you want to use other serialization format (2020) or this benchmark (2022) for dynamic structure
答案2
得分: 16
结构体的序列化通常使用encoding
包。然而,这只适用于公共字段。如果你还需要序列化私有字段,可以参考这个答案作为替代方案。
你有几种编码选择(二进制、文本、像这个例子中的json结构体、xml等)。例如,项目cupcake/rdb
使用encoding/binary
来实现解析和编码Redis的RDB文件格式(内存中存储的二进制表示)。
另一个例子是guregu/rediscache
,一个用于在Redis中缓存数据的小型库。
英文:
Serialization of a struct generally uses the encoding
package. However, that will work for public fields only. If you also need to serialize private fields, see this answer as an alternative.
You have several encoding choices (binary, text, json as in this example for a struct, xml, etc.). For example, the project cupcake/rdb
uses encoding/binary
to implement parsing and encoding of the Redis RDB file format (a binary representation of the in-memory store).
Another example is guregu/rediscache
, a small library for caching data in Redis.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论