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

huangapple go评论73阅读模式
英文:

How to set array document into redis in Golang?

问题

我在将文档插入Redis时遇到了问题。

我在Go中有一个数据结构:

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

我想将这样的数据添加到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]] 

但是当我运行Redis.HMSet("test", structs.Map(ret))时,它返回错误:redis: can't marshal postgresql.ArticleCovers (consider implementing encoding.BinaryMarshaler)

谁能帮我解决这个问题,非常感谢!

英文:

I have a problemwhen insert document in to redis.

I have a struct of data in 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:

[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).

Who can help me fix my problem, thks you so much!

答案1

得分: 3

根据错误信息所说,你需要为你的ArticleCovers类型实现BinaryMarshaler接口:

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
}

请注意,这只添加了IDArticleTypeID字段。我不知道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))
}

我不知道这种格式是否适合你的数据。你可能想要使用一种定义好的编码格式,比如json。

你可能还想要实现BinaryUnmarshaler接口。具体实现留作练习。;-)

英文:

Like the error message says, you need to implement the BinaryMarshaler interface for your ArticleCovers type:

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. I don't know what
the ArticleCovers and Address types look like, but often you want to call
the same methods on that:

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.

You will probably also want to implement the BinaryUnmarshaler interface.
Doing that is left as an exercise 如何在Golang中将数组文档设置到Redis中?

答案2

得分: 1

如Carpetsmoker所说,关于JSON编码,以下是如何实现的:

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

在解码时,您可以使用BinaryUnmarshaler

您可以在我的博客文章中查看更好的示例。

英文:

As Carpetsmoker was saying about the JSON encoding this is how to do it:

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

Where when decoding you'd use BinaryUnmarshaler

You can checkout for better example here at my blog post

1: https://golang.org/pkg/encoding/#BinaryUnmarshaler "BinaryUnmarshaler"
2: https://medium.com/@nevio/proper-way-how-to-marshal-and-unmarshal-golang-structs-within-the-redis-cache-855423902787 "how-to-marshal-and-unmarshal-golang-structs-redis"

答案3

得分: 0

当直接将任何类型的对象保存到Redis中时,它会尝试对其进行二进制哈希处理,因此您应该实现MarshalBinary方法使其正常工作。其思想是将值简单地以二进制格式或由客户端内部处理的字符串格式保存。

因此,针对保存对象的一个可能且简单的解决方案是以字符串格式保存它们,您仍然可以使用不同的编组技术,比如JSON

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

尽管JSON是一种简单的方法,但是通过使用二进制而不是基于文本的编码,您可以获得更好的性能。gop是一个可以对对象进行编码和解码的包。此外,Protocol Buffers现在被广泛使用,特别是在涉及不同语言和集成的情况下。

这里有一个使用gopMarshalBinary的简单示例

英文:

When saving any kind of object into redis directly, it tries to binary hash it so you should implement MarshalBinary to make it work. 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.

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. gop is package where it can encode and decode objects. 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

huangapple
  • 本文由 发表于 2017年6月27日 10:34:12
  • 转载请务必保留本文链接:https://go.coder-hub.com/44771474.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定