go语言学习之gzip包解读

  打开浏览器浏览网页时,我们可以看到各种各样的文字、图片、视频等等各式各样的信息。那么浏览器是怎样和服务器交互这些信息的呢?通过分析不难发现,这些信息往往要经过统一编码之后,才进行传递。今天,我们来通过分析gzip.go文件,了解gzip压缩的实现,进而去实现自己编码网页信息。

数据结构定义

1. 常量定义

常量定义来自deflate定义,阅读deflate.go文件,可以获得相关值。这些常量用来标记数据的状态和压缩方式。

// These constants are copied from the flate package, so that code that imports
// "compress/gzip" does not also have to import "compress/flate".
const (
    NoCompression      = flate.NoCompression  
    BestSpeed          = flate.BestSpeed
    BestCompression    = flate.BestCompression
    DefaultCompression = flate.DefaultCompression
    HuffmanOnly        = flate.HuffmanOnly
)

deflate.go中对这些常量的定义如下:

const (
    NoCompression      = 0
    BestSpeed          = 1
    BestCompression    = 9
    DefaultCompression = -1
    HuffmanOnly = -2
)
2. Writer结构体的定义

Writer结构体定义了压缩常用的变量,为后续接口函数的实现提供了便利。

type Writer struct {
    Header      // written at first call to Write, Flush, or Close
    w           io.Writer
    level       int
    wroteHeader bool
    compressor  *flate.Writer
    digest      uint32 // CRC-32, IEEE polynomial (section 8)
    size        uint32 // Uncompressed size (section 2.3.1)
    closed      bool
    buf         [10]byte
    err         error
}

其中,

  • Header:定义来自gunzip.go,定义了gzip数据头部的一些信息,稍后我们会详细解释
  • w:声明为io.Writer接口,调用相关函数完成数据向缓冲区的写入
  • level:压缩的等级。范围为[-2, 9]
  • wroteHeader:表示gzip头部信息是否已经填充
  • compressor:压缩器
  • digest: 32位的循环冗余校验位。不懂请点击这里
  • size:未压缩数据的长度
  • closed:该Writer是否关闭
  • buf:存储gzip头部的信息
  • err:处理Writer相关函数中的一切错误

函数定义

1. NewWriter

该方法创建并使用io.Writer初始化一个Writer。

func NewWriter(w io.Writer) *Writer {
    z, _ := NewWriterLevel(w, DefaultCompression)
    return z
}
2. init

该方法初始化一个Writer。

func (z *Writer) init(w io.Writer, level int) {
    compressor := z.compressor
    if compressor != nil {
        compressor.Reset(w)
    }
    *z = Writer{
        Header: Header{
            OS: 255, // unknown
        },
        w:          w,
        level:      level,
        compressor: compressor,
    }
}
3. NewWriterLevel

该方法创建一个Writer,并且定义了Writer中level的值。

func NewWriterLevel(w io.Writer, level int) (*Writer, error) {
    if level < HuffmanOnly || level > BestCompression {
        return nil, fmt.Errorf("gzip: invalid compression level: %d", level)
    }
    z := new(Writer)
    z.init(w, level)
    return z, nil
}
4. Reset

该方法重置Writer的状态,从而可以复用一个Writer。

func (z *Writer) Reset(w io.Writer) {
    z.init(w, z.level)
}
5. writeBytes

该方法把一段字节数据的长度写入z.w。

func (z *Writer) writeBytes(b []byte) error {
    if len(b) > 0xffff {
        return errors.New("gzip.Write: Extra data is too large")
    }
    //var le = binary.LittleEndian
    le.PutUint16(z.buf[:2], uint16(len(b)))
    _, err := z.w.Write(z.buf[:2])
    if err != nil {
        return err
    }
    _, err = z.w.Write(b)
    return err
}
  • 注解1
le.PutUint16(z.buf[:2], uint16(len(b)))

是将16位无符号整数输出为小端模式。PutUint16的定义如下:

func (littleEndian) PutUint16(b []byte, v 
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kiloveyousmile

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值