go 自己实现一个gob编解码
代码库 为什么要写这么一个编解码golang内部也实现了一个gob的二进制编解码,接口简单,使用方便,但是它对interface的支持不是很好, var in []interface{} = []interface{}{1, 1.5,"abc","123",map[int]int{1: 1, 2: 2, 3: 3}}
enc.Encode(in)
var out []interface{}
dec.Decode(&out)
fmt.Println(out)
使用gob是无法对上面的in进行正确编解码的,为了解决上面的问题,所以我需要自己实现一个可以完美支持任意内置类型的interface{}的编码系统 想法为了达到这样的目的,我们需要将每一个interface的类型ID和值编码都编码进二进制流中. 这样就可以在解析的时候,根据对应的类型ID生成值并且解析值。 因为需要自动生成类型ID的值,所以对于自定义类型我们需要进行注册。目前只支持自定义的结构体注册。 使用package gob_test
import "github.com/sydnash/lotou/encoding/gob"
import "fmt"
import "testing"
import "reflect"
func TestType(t *testing.T) {
enc := gob.NewEncoder()
a := make([]interface{}, 0, 10)
a = append(a,int(-5))
a = append(a,int8(-1))
a = append(a,int16(-2))
a = append(a,int32(-3))
a = append(a,int64(-4))
a = append(a,uint(6))
a = append(a,uint8(7))
a = append(a,uint16(8))
a = append(a,uint32(9))
a = append(a,uint64(10))
a = append(a,float32(0.99999))
a = append(a,float64(0.9999999999))
a = append(a,"this is a string")
a = append(a,"这也是一个string")
a = append(a,&gob.T1{10,"哈哈,这都可以?", -100})
a = append(a,&gob.T2{gob.T1{10, -100},"那么这样还可以吗?"})
a = append(a,gob.T1{10,gob.T2{gob.T1{10,true)
a = append(a,false)
a = append(a,[3]int{1, 2, 3})
a = append(a,[]byte{})
m := make(map[int]string)
m[1] = "map的第一个元素"
m[1] = "map的第二个元素"
a = append(a,m)
s := make([]string, 2)
s = append(s,"这是slice的元素")
a = append(a,s)
str := "这是一个[]byte"
s1 := []byte(str)
a = append(a,s1)
b := make([]interface{}, 10)
b = append(b,m)
b = append(b,s)
b = append(b,s1)
a = append(a,b)
a = append(a,a)
//start encode
for _,v := range a {
enc.Encode(v)
}
//create decoder
dec := gob.NewDecoder()
dec.SetBuffer(enc.Buffer())
var ok bool = true
var r interface{}
idx := 0
for ok {
//decode
r,ok = dec.Decode()
fmt.Println(r,reflect.TypeOf(r),ok)
if ok {
//check decode is ok?
if !reflect.DeepEqual(r,a[idx]) {
t.Errorf("%v is not equal to %v at idx %v",r,a[idx],idx)
}
if reflect.TypeOf(r) != reflect.TypeOf(a[idx]) {
t.Errorf("%v is not equal to %v at idx %v",reflect.TypeOf(a[idx]),idx)
}
idx++
}
}
}
可以编解码任意的内置类型的slice map。 主要实现类型编码
类型ID由structID、指针深度、reflect.kind三部分拼接而成, func gernerateId(kind,depth,structId uint) uint16 {
id := uint16(structId)<<8 | uint16(depth)<<5 | uint16(kind)
return id
}
其中structID在注册struct类型的时候分配 解码和创建在解析出来类型id之后,通过一个预定义的map映射到reflect.type上,然后通过reflect.new函数来创建对应的类型的值,最终通过reflect.Value.interface返回为 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |