英文:
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
}
请注意,这只添加了ID
和ArticleTypeID
字段。我不知道ArticleCovers
和Address
类型的具体结构,但通常你可能需要调用相同的方法:
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
答案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现在被广泛使用,特别是在涉及不同语言和集成的情况下。
这里有一个使用gop
和MarshalBinary
的简单示例。
英文:
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
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论