在日常工作中,如果遇到数据量大的情况,在 db 中是不能直接存储某些字段的,一般会用 json 进行marshal 为 byte 再存入。但是如果此时占用空间依旧过大,则可以考虑再用 gzip 还进一步压缩。
Gzip 包go标准库的gzip包中提供了两个 *** 作,分别是压缩和解压
常量和变量
const (
NoCompression = flate.NoCompression // 不压缩
BestSpeed = flate.BestSpeed // 最快速度
BestCompression = flate.BestCompression // 最佳压缩比
DefaultCompression = flate.DefaultCompression // 默认压缩比
)
var (
// 当读取gzip数据时发现无效的校验和时将返回该错误
ErrChecksum = errors.New("gzip: invalid checksum")
// 当读取gzip数据时发现无效的数据头时将返回该错误
ErrHeader = errors.New("gzip: invalid header")
)
//数据头结构
type Header struct {
Comment string // 文件注释
Extra []byte // 附加数据
ModTime time.Time // 文件修改时间
Name string // 文件名
OS byte // *** 作系统类型
}
Gzip 用法
压缩
func Encode(input []byte) ([]byte, error) {
// 创建一个新的 byte 输出流
var buf bytes.Buffer
// 创建一个新的 gzip 输出流
gzipWriter := gzip.NewWriter(&buf)
// 将 input byte 数组写入到此输出流中
_, err := gzipWriter.Write(input)
if err != nil {
_ = gzipWriter.Close()
return nil, err
}
if err := gzipWriter.Close(); err != nil {
return nil, err
}
// 返回压缩后的 bytes 数组
return buf.Bytes(), nil
}
解压
func Decode(input []byte) ([]byte, error) {
// 创建一个新的 gzip.Reader
bytesReader := bytes.NewReader(input)
gzipReader, err := gzip.NewReader(bytesReader)
if err != nil {
return nil, err
}
defer func() {
// defer 中关闭 gzipReader
_ = gzipReader.Close()
}()
buf := new(bytes.Buffer)
// 从 Reader 中读取出数据
if _, err := buf.ReadFrom(gzipReader); err != nil {
return nil, err
}
return buf.Bytes(), nil
}
与 json 搭配使用
// 压缩
func MarshalToJsonWithGzip(jsonData anyStruct) []byte {
dataAfterMarshal, _ := json.Marshal(jsonData)
dataAfterGzip, err := gzip.Encode(dataAfterMarshal)
if err != nil {
return nil
}
return dataAfterGzip
}
// 解压
func UnmarshalDataFromJsonWithGzip(msg []byte) (*anyStruct, error) {
dataAfterDecode, err := gzip.Decode(msg)
if err != nil {
return nil, err
}
data := &anyStruct{}
err = json.Unmarshal(dataAfterDecode, data)
if err != nil {
return nil, err
}
return data, nil
}
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)