- 函数
- Serialize 函数
- Unserialize 函数
- Marshal 函数
- Unmarshal 函数
- RegisterSliceEncoder 函数
- RegisterMapEncoder 函数
- Register 函数
- GetStructType 函数
- GetAlias 函数
- GetTag 函数
函数
Serialize 函数
- func Serialize(v interface{}, simple bool) []byte
将 v
序列化为字节切片。simple
参数的含义与 Writer
结构体的序列化的 simple
参数相同。
Unserialize 函数
- func Unserialize(b []byte, p interface{}, simple bool)
将字节切片数据 b
反序列化到 p
所指向的变量中,p
是一个指向反序列化变量的指针。simple
参数的含义与 Reader
结构体的序列化的 simple
参数相同。
Marshal 函数
- func Marshal(v interface{}) []byte
相当于 Serialize(v, true)
。
Unmarshal 函数
- func Unmarshal(b []byte, p interface{})
相当于 Unserialize(b, p, true)
。
RegisterSliceEncoder 函数
- func RegisterSliceEncoder(s interface{}, encoder func(*Writer, interface{}))
该函数用于注册一个 slice 编码器实现对 slice 的快速的 hprose 序列化。hprose 对如下 slice 类型已经提供了内置的快速编码器:
- []bool
- []int
- []int8
- []int16
- []int32
- []int64
- []uint
- []uint8
- []uint16
- []uint32
- []uint64
- []uintptr
- []float32
- []float64
- []complex64
- []complex128
- []string
- [][]byte
- []interface{}
用户不需要为上述 slice 类型注册自定义编码器。
对于没有提供快速编码器的类型,hprose 采用反射的方式进行序列化。如果用户想要加快某个复杂的 slice 类型的序列化,可以使用该函数来注册自定义编码器,下面来看一个例子:
- package main
- import (
- "fmt"
- "time"
- "github.com/hprose/hprose-golang/io"
- "github.com/hprose/hprose-golang/util"
- )
- func mySliceEncoder(w *io.Writer, v interface{}) {
- slice := v.([]map[string]interface{})
- var buf [20]byte
- for i := range slice {
- w.WriteByte(io.TagMap)
- w.Write(util.GetIntBytes(buf[:], int64(len(slice[i]))))
- w.WriteByte(io.TagOpenbrace)
- for key, val := range slice[i] {
- w.WriteString(key)
- w.Serialize(val)
- }
- w.WriteByte(io.TagClosebrace)
- }
- }
- func test(slice []map[string]interface{}) {
- start := time.Now()
- for i := 0; i < 500000; i++ {
- io.Marshal(slice)
- }
- stop := time.Now()
- fmt.Println((stop.UnixNano() - start.UnixNano()) / 1000000)
- }
- func main() {
- slice := make([]map[string]interface{}, 10)
- for i := 0; i < 10; i++ {
- slice[i] = make(map[string]interface{})
- slice[i]["id"] = i
- }
- test(slice)
- io.RegisterSliceEncoder(([]map[string]interface{})(nil), mySliceEncoder)
- test(slice)
- }
该程序运行结果为:
844
664
我们看到,实现快速编码器之后,效率提高了大约 20% 左右。当然实现快速编码器需要了解 hprose 的编码规范。如果上面的编码器只是实现为:
- func mySliceEncoder(w *io.Writer, v interface{}) {
- slice := v.([]map[string]interface{})
- for i := range slice {
- w.Serialize(slice[i])
- }
- }
并不会加快序列化速度,反而会比默认方式更慢。所以,在自定义编码器时,最好测试一下注册前后的性能对比。
RegisterSliceEncoder
函数的第一个参数是编码器所要序列化的数据类型的一个实例。它必须是一个 slice 类型的实例,并且跟后面注册的编码器中所序列化的类型相一致。
RegisterMapEncoder 函数
- func RegisterMapEncoder(m interface{}, encoder func(*Writer, interface{}))
该函数用于注册一个 map 编码器实现对 map 的快速的 hprose 序列化。hprose 对如下 map 类型已经提供了内置的快速编码器:
- map[string]string
- map[string]interface{}
- map[string]int
- map[int]int
- map[int]string
- map[int]interface{}
- map[interface{}]interface{}
- map[interface{}]int
- map[interface{}]string
用户不需要为上述 map 类型注册自定义编码器。
对于没有提供快速编码器的类型,hprose 采用反射的方式进行序列化。如果用户想要加快某个其它 map 类型的序列化,可以使用该函数来注册自定义编码器,下面来看一个例子:
- package main
- import (
- "fmt"
- "math"
- "time"
- "github.com/hprose/hprose-golang/io"
- )
- func stringFloat64MapEncoder(w *io.Writer, v interface{}) {
- m := v.(map[string]float64)
- for key, val := range m {
- w.WriteString(key)
- w.WriteFloat(val, 64)
- }
- }
- func test(m map[string]float64) {
- start := time.Now()
- for i := 0; i < 500000; i++ {
- io.Marshal(m)
- }
- stop := time.Now()
- fmt.Println((stop.UnixNano() - start.UnixNano()) / 1000000)
- }
- func main() {
- m := make(map[string]float64)
- m["e"] = math.E
- m["pi"] = math.Pi
- m["ln2"] = math.Ln2
- test(m)
- io.RegisterMapEncoder((map[string]float64)(nil), stringFloat64MapEncoder)
- test(m)
- }
该程序运行结果为:
680
429
我们看到,实现快速编码器之后,效率提高了大约 35% 左右。
RegisterMapEncoder
函数的第一个参数是编码器所要序列化的数据类型的一个实例。它必须是一个 map 类型的实例,并且跟后面注册的编码器中所序列化的类型相一致。
Register 函数
- func Register(proto interface{}, alias string, tag ...string)
该函数用于注册一个可序列化和反序列化的自定义结构体。
第一个参数 proto
为注册的结构体对象,它也可以是结构体指针。
第二个参数 alias
为注册的结构体的别名,该名称可以跟结构体类型名称相同,也可以不同。它用于在不同语言的不同定义之间进行类型映射。
第三个参数 tag
是可选的(可以是 0 个或 1 个,但不支持多个),它用于指定序列化字段别名的 tag
标签名。
假设有如下结构体定义:
- type User struct {
- Name string `json:"name"`
- Age int `json:"age"`
- Password string `json:"-"`
- }
那么可以这样注册:
- func init() {
- io.Register((*User)(nil), "User", "json")
- }
注册之后的 User
类型的对象,在序列化时,字段名按照 json
标签对应的名称进行序列化,如果 json
标签对应的名称为 "-"
,那么该字段将不会被序列化。另外,私有字段也不会被序列化。当没有指定标签时,字段名会自动按照小写首字母的名称进行序列化。
GetStructType 函数
- func GetStructType(alias string) (structType reflect.Type)
获取用 Register
函数注册的类型。
GetAlias 函数
- func GetAlias(structType reflect.Type) string
获取用 Register
函数注册的类型对应的别名。
GetTag 函数
- func GetTag(structType reflect.Type) string
获取用 Register
函数注册的类型对应的标记。