在涉及 Go 和 C 的混合系统开发中,经常需要让两种语言处理同一份压缩数据。zlib 是一个成熟且被广泛支持的压缩库,Go 标准库与 C 的 zlib 开发包都遵循同样的 RFC 1950 与 1951 规范,因此只要使用正确的参数,就能实现完全兼容的压缩与解压缩。

Go 中使用 zlib 压缩与解压缩
Go 标准库的 compress/zlib 包封装了 zlib 格式,使用起来非常直观。下面的示例展示了如何压缩一段字节数据,以及如何从压缩数据中还原原文。
package main
import (
"bytes"
"compress/zlib"
"io"
"log"
)
// 使用 zlib 压缩数据
func compress(data []byte) []byte {
var buf bytes.Buffer
w := zlib.NewWriter(&buf)
w.Write(data)
w.Close()
return buf.Bytes()
}
// 使用 zlib 解压缩数据
func decompress(data []byte) []byte {
r, err := zlib.NewReader(bytes.NewReader(data))
if err != nil {
log.Fatal(err)
}
defer r.Close()
out, _ := io.ReadAll(r)
return out
}
func main() {
src := []byte("hello from go and c with zlib")
c := compress(src)
d := decompress(c)
log.Println(string(d))
}
C 中使用 zlib 压缩与解压缩
C 语言通过 zlib.h 提供的 API 直接操作压缩流。下面代码演示了如何用默认的压缩级别压缩字符串,再将其解压回来。注意压缩级别与 Go 的默认级别保持一致即可兼容。
#include <stdio.h>
#include <string.h>
#include <zlib.h>
// 压缩数据,输出到 out,并返回压缩后长度
int compress_data(const char *src, int srclen, char *out, int outcap) {
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
deflateInit(&strm, Z_DEFAULT_COMPRESSION);
strm.avail_in = srclen;
strm.next_in = (Bytef *)src;
strm.avail_out = outcap;
strm.next_out = (Bytef *)out;
deflate(&strm, Z_FINISH);
int len = outcap - strm.avail_out;
deflateEnd(&strm);
return len;
}
// 解压缩数据
int decompress_data(const char *src, int srclen, char *out, int outcap) {
z_stream strm;
strm.zalloc = Z_NULL;
strm.zfree = Z_NULL;
strm.opaque = Z_NULL;
inflateInit(&strm);
strm.avail_in = srclen;
strm.next_in = (Bytef *)src;
strm.avail_out = outcap;
strm.next_out = (Bytef *)out;
inflate(&strm, Z_FINISH);
int len = outcap - strm.avail_out;
inflateEnd(&strm);
return len;
}
int main() {
char src[] = "hello from go and c with zlib";
char buf[256];
int clen = compress_data(src, strlen(src), buf, 256);
char out[256];
int dlen = decompress_data(buf, clen, out, 256);
out[dlen] = 0;
printf("%sn", out);
return 0;
}
保证跨语言兼容的要点
- 使用默认的 zlib 数据头,即带 zlib 头和 adler32 校验的格式,Go 的 zlib.Writer 与 C 的 deflateInit 默认都生成这种格式。
- 压缩级别建议统一使用 Z_DEFAULT_COMPRESSION,避免两端级别不一致造成调试困惑。
- 传输时直接传递压缩后的二进制字节流,不要额外做 Base64 之外的文本编码混淆,除非两端约定一致。
小结
只要遵循相同的 zlib 格式与参数,Go 与 C 之间完全可以互相解压对方生成的压缩数据。实际项目中,可以将 C 侧产生的压缩包发送给 Go 服务,或由 Go 压缩后交给 C 模块处理,无需担心兼容性问题。
zlibGoC_compression修改时间:2026-07-30 09:00:21