简体   繁体   English

如何在Golang中将数组文档设置为Redis?

[英]How to set array document into redis in Golang?

I have a problemwhen insert document in to redis. 将文档插入Redis时出现问题。

I have a struct of data in Go: 我在Go中有一个数据结构:

type ArticleCovers struct {
    ID             int
    Covers         ArticleCovers
    ArticleTypeID  int
    Address        Address     `gorm:"ForeignKey:AddressID"`
}

I want to add a data like this into Redis: 我想将这样的数据添加到Redis中:

[ID:1 Cover:[http://chuabuuminh.vn/UserImages/2012/12/10/1/chinh_dien_jpg.jpg] ArticleTypeID:1 Address:map[Street: City:<nil> District:<nil> DistrictID:0 ID:0 Slug: Lat:0 Long:0 Ward:<nil> WardID:0 CityID:0]] 

But when I run Redis.HMSet("test", structs.Map(ret)) it return the error: redis: can't marshal postgresql.ArticleCovers (consider implementing encoding.BinaryMarshaler) . 但是,当我运行Redis.HMSet("test", structs.Map(ret))它返回错误: redis: can't marshal postgresql.ArticleCovers (consider implementing encoding.BinaryMarshaler)

Who can help me fix my problem, thks you so much! 谁能帮助我解决我的问题,您真高兴!

Like the error message says, you need to implement the BinaryMarshaler interface for your ArticleCovers type: 像错误消息说,您需要实现BinaryMarshaler界面为你ArticleCovers类型:

type ArticleCovers struct {
    ID             int
    Covers         ArticleCovers
    ArticleTypeID  int
    Address        Address     `gorm:"ForeignKey:AddressID"`
}

func (ac ArticleCovers) MarshalBinary() ([]byte, error) {
    return []byte(fmt.Sprintf("%v-%v", ac.ID, ac.ArticleTypeID)), nil
}

Note that this only adds the ID and ArticleTypeID fields. 请注意,这只会添加IDArticleTypeID字段。 I don't know what the ArticleCovers and Address types look like, but often you want to call the same methods on that: 我不知道ArticleCoversAddress类型是什么样,但是通常您想在其上调用相同的方法:

func (ac ArticleCovers) MarshalBinary() ([]byte, error) {
    covers, err := ac.Covers.MarshalBinary()
    if err != nil {
        return nil, err
    }
    address, err := ac.Address.MarshalBinary()
    if err != nil {
        return nil, err
    }

    return []byte(fmt.Sprintf("%v-%v-%v-%v",
        ac.ID, ac.ArticleTypeID, covers, address)
}

I don't know if this format makes sense for your data. 我不知道这种格式对您的数据是否有意义。 You may want to use a defined encoding format such as json. 您可能要使用定义的编码格式,例如json。

You will probably also want to implement the BinaryUnmarshaler interface. 您可能还希望实现BinaryUnmarshaler接口。 Doing that is left as an exercise ;-) 做那剩下的练习;-)

As Carpetsmoker was saying about the JSON encoding this is how to do it: 正如Carpetsmoker所说的JSON编码一样,这是怎么做的:

func (ac ArticleCovers) MarshalBinary() ([]byte, error) {
  return json.Marshal(ac)
}

Where when decoding you'd use BinaryUnmarshaler 解码时在哪里使用BinaryUnmarshaler

You can checkout for better example here at my blog post 您可以在我的博客文章中查看更好的示例

When saving any kind of object into redis directly, it tries to binary hash it so you should implement MarshalBinary to make it work. 将任何类型的对象直接保存到Redis中时,它会尝试对其进行二进制哈希处理,因此您应该实现MarshalBinary使其起作用。 the idea is to save the value simply in a binary format or string format that is handled by the client internally. 想法是将值简单地保存为客户端内部处理的二进制格式或字符串格式。

So with that being said, one possible and easy solution of saving objects is save them in a string format, you can still use different marshaling techniques like JSON to do this. 话虽这么说,保存对象的一种可能的简便方法是将它们保存为字符串格式,您仍然可以使用不同的封送处理技术(例如JSON来执行此操作。

func Save(obj interface{}) error {
  Redis.HMSet("test", json.Marshal(obj))
}

Although json is an easy way of doing this, but you can have better performance by using binary instead of text-based encoding. 尽管json是执行此操作的一种简便方法,但是通过使用二进制而不是基于文本的编码,可以提高性能。 gop is package where it can encode and decode objects. gop是可以对对象进行编码和解码的软件包。 also protocol buffers is now widely used especially in such cases where we have different languages and integrations. 协议缓冲区现在也被广泛使用,尤其是在我们具有不同语言和集成的情况下。

Here is a simple example with gop and MarshalBinary 这是使用gopMarshalBinary的简单示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM