前言
有些时候,我们会发现,[]byte
类型在 struct
中,是必不可少的结构体,因为用了[]byte
代表可以存储字节数据,也可以叫做二进制安全的存储。代表可以存储任何数据。
如何才能做到在序列化json的情况下,可以Println
出一个可读性的在struct
的[]byte
呢?
实现
最近我在开发我们的部门的配置服务,需要提供一个配置工具。里面设计的一个struct,有一个[]byte
类型,就是用来存储实际数据的。但是我们在这里的时候,我们有一个查看原始数据的需求,因为我们的数据经过了加密
,和压缩
,最终才会放到该结构体。
简化结构体,这里列举一下例子:
1 | type V []byte |
这里我们看到,我们这里的Value
实际就是一个[]byte
,我们把这个结构体经过json.Marshal
之后推送到远端kv
服务中,一切都正常。
但是当我们需要查看的时候,就需要从远端的kv
拉回来,经过json.Unmarsha
处理,这个时候,我们会发现:
1 | {"PublishTime":1630636657,"PublishDateTime":"2021-09-03 02:37:37.8693941 +0000 UTC m=+0.015759101","Value":"MTIzCg=="} |
这里,我们看到Value
是一个经过base64
加密过的数据,这是因为默认情况下[]byte
将会把数据经过base64
变成字符串
来符合json数据类型
。那么我们有什么版本让他显示出原来真是的数据呢?
这里我使用了一个方案,借助多一个数据结构,对T V
进行一个重组
。
1 | type VO []byte |
定义多一个大体上一致
的结构体,注意此时的Value
不再是V
,而是VO
,我们对VO
自定义json序列化的行为,那就是把base64
的行为给去掉。
这样子,我们得到的数据就会是
1 | {"PublishTime":1630636657,"PublishDateTime":"2021-09-03 02:37:37.8693941 +0000 UTC m=+0.015759101","Value":123} |
细心的朋友一定发现了问题所在,那就是Value
和ValueReadable
怎么进行转换。
因为你存的时候是通过Value
进行marshal
的,那么你的unmarsha
行为一定要对应才能解到正确的数据。
所以这里,就是我们的一个重点,我们需要借助unsafe.Pointer
1 | // because []byte in struct will be base64encode |
我们利用unsafe
的指针
数据类型,进行一个强制转换,为什么会成功呢,因为在内存对齐的结构上,这2个对象的内存是一致的,所以我们就可以进行强制转换,而不用担心有panic
的产生。这只是unsafe
指针的一个灵活运用。但是可以达到我们的目的,十分的有效果。
1 | {"PublishTime":1630636657,"PublishDateTime":"2021-09-03 02:37:37.8693941 +0000 UTC m=+0.015759101","Value":123} |
转换后,就可以看到我原本的数据了 123
.