tinylib/msgp
GitHub: tinylib/msgp
一个高性能的 Go 语言 MessagePack 代码生成器与序列化库,通过编译期生成类型安全的编解码代码实现零分配序列化。
Stars: 1947 | Forks: 200
# MessagePack 代码生成器
[](https://pkg.go.dev/github.com/tinylib/msgp)
[](https://github.com/tinylib/msgp/actions/workflows/test.yml)
[](https://github.com/tinylib/msgp/actions/workflows/validate.yml)
这是一个用于 [MessagePack](http://msgpack.org) 的代码生成工具和序列化库。你可以[在 wiki 中](http://github.com/tinylib/msgp/wiki)或访问 [msgpack.org](http://msgpack.org) 阅读更多关于 MessagePack 的信息。
### 为什么选择它?
- 使用 Go 作为你的 schema 语言
- 高性能
- [JSON 互操作性](https://pkg.go.dev/github.com/tinylib/msgp/msgp#CopyToJSON)
- [用户自定义扩展](http://github.com/tinylib/msgp/wiki/Using-Extensions)
- 类型安全
- 编码灵活性
### 快速开始
首先安装 `msgp` 生成器命令。在 Go 中,这可以通过 `go install github.com/tinylib/msgp@latest` 来完成。
在源文件中,包含以下指令:
```
//go:generate msgp
```
`msgp` 命令将为文件中所有导出的类型声明生成序列化方法。
你可以[在此处阅读更多关于代码生成选项的信息](http://github.com/tinylib/msgp/wiki/Using-the-Code-Generator)。
### 使用
字段名称的设置方式与 `encoding/json` 包基本相同。例如:
```
type Person struct {
Name string `msg:"name"`
Address string `msg:"address"`
Age int `msg:"age"`
Hidden string `msg:"-"` // this field is ignored
unexported bool // this field is also ignored
}
```
默认情况下,代码生成器将满足 `msgp.Sizer`、`msgp.Encodable`、`msgp.Decodable`、
`msgp.Marshaler` 和 `msgp.Unmarshaler`。经过精心设计的应用程序可以使用这些方法实现
零堆内存分配的封送/解送(marshalling/unmarshalling)。
虽然 `msgp.Marshaler` 和 `msgp.Unmarshaler` 与标准库的
`json.Marshaler` 和 `json.Unmarshaler` 非常相似,但 `msgp.Encodable` 和 `msgp.Decodable` 对于
流序列化非常有用。(`*msgp.Writer` 和 `*msgp.Reader` 本质上是
`*bufio.Writer` 和 `*bufio.Reader` 的协议感知版本。)
需要注意的一点是,msgp 是针对*单个文件*进行操作的。
这意味着如果你的 struct 包含在其他文件中定义的类型,则也必须对这些文件进行处理。
### 功能
- 极快的生成代码
- 测试和基准测试生成
- JSON 互操作性(参见 `msgp.CopyToJSON() and msgp.UnmarshalAsJSON()`)
- 支持复杂的类型声明
- 原生支持 Go 的 `time.Time`、`complex64` 和 `complex128` 类型
- 同时生成面向 `[]byte` 和面向 `io.Reader/io.Writer` 的方法
- 支持任意的类型系统扩展
- [预处理器指令](http://github.com/tinylib/msgp/wiki/Preprocessor-Directives)
- 基于文件的依赖模型意味着无论源代码树有多大,代码生成都很快。
考虑以下代码:
```
const Eight = 8
type MyInt int
type Data []byte
type Struct struct {
Which map[string]*MyInt `msg:"which"`
Other Data `msg:"other"`
Nums [Eight]float64 `msg:"nums"`
}
```
只要 `MyInt` 和 `Data` 的声明与 `Struct` 位于同一个文件中,解析器就会在生成其方法之前确定 `MyInt` 和 `Data` 的类型信息可以传递到 `Struct` 的定义中。
#### 扩展
MessagePack 支持通过“扩展”定义你自己的类型,这实际上就是
数据“类型”(`int8`)和原始二进制数据的组合。你[可以在 wiki 中看到一个完整的示例。](http://github.com/tinylib/msgp/wiki/Using-Extensions)
### 状态
基本稳定,因为 `/msgp` 库在过去一年多的时间里没有发生过破坏性更新。出于性能原因,
新版本的代码生成的代码可能与旧版本不同。我(@philhofer)知道一些
对稳定性要求极高的商业应用程序正在使用此代码,并且效果良好。但是,后果自负。
你可以在 [wiki 中](http://github.com/tinylib/msgp/wiki)阅读更多关于 `msgp` 如何将 MessagePack 类型映射到 Go 类型的信息。
以下是一些已知的限制/约束:
- 对于已处理源文件之外的标识符,(乐观地)假定它们满足生成器的接口。如果情况并非如此,你的代码将无法编译。
- 与大多数序列化器一样,`chan` 和 `func` 字段以及未导出的字段将被忽略。
- `interface{}` 的编码仅限于内置类型或具有显式编码方法的类型。
- _Map 必须具有 `string` 类型的键。_ 这是故意的(因为它保留了 JSON 的互操作性。)尽管 MessagePack 标准并未禁止非 string 类型的 map 键,但许多序列化器都施加了此限制。(这也意味着*任何*格式正确的 `struct` 都可以反序列化为 `map[string]interface{}`。)此规则的唯一例外是,反序列化器允许你读取编码为 `bin` 类型的 map 键,这是因为某些旧版编码允许这样做。(然而,这些值仍将被转换为 Go 的 `string`,并在重新编码时转换为 `str` 类型。在这种情况下,用户有责任确保 map 键是 UTF-8 安全的。)同样的规则也适用于 JSON 转换。
如果生成的代码能够编译通过,那么很有可能一切正常。(另外,我们为你生成了测试。)*请务必、请务必、请务必*在提交 issue 如果你认为生成器正在编写损坏的代码。
### 性能
如果你喜欢基准测试,请参见[这里](http://bravenewgeek.com/so-you-wanna-go-fast/)和[这里](https://github.com/alecthomas/go_serialization_benchmarks)。
正如预期的那样,处理 `[]byte` 的生成方法对于小对象来说更快,但对于大对象(> 2KB),`io.Reader/Writer` 方法通常在内存方面更高效(并且,在某种程度上也更快)。
标签:EVTX分析, Go, MessagePack, Ruby工具, SOC Prime, 代码生成, 序列化, 开发工具, 日志审计, 渗透测试工具