本代码片段根源是网上的序列化包,是保存到本地之后,进行的更改,其中引入了【decimal】包来解决反序列化数字精度问题,代码如下:
package utils
import (
"bytes"
"fmt"
"reflect"
"sort"
"strconv"
"strings"
"github.com/shopspring/decimal"
)
const UNSERIALIZABLE_OBJECT_MAX_LEN = int64(10 * 1024 * 1024 * 1024)
func Marshal(value interface{}) ([]byte, error) {
if value == nil {
return MarshalNil(), nil
}
t := reflect.TypeOf(value)
switch t.Kind() {
case reflect.Bool:
return MarshalBool(value.(bool)), nil
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64,
reflect.Uint, reflect.Uint16, reflect.Uint32, reflect.Uint64,
reflect.Float32, reflect.Float64:
return MarshalNumber(value), nil
case reflect.String:
return MarshalString(value.(string)), nil
case reflect.Map:
return MarshalMap(value)
case reflect.Slice:
return MarshalSlice(value)
case reflect.Struct:
return []byte("d:" + value.(decimal.Decimal).String() + ";"), nil
default:
return nil, fmt.Errorf("Marshal: Unknown type %T with value %#v", t, value)
}
}
func MarshalNil() []byte {
return []byte("N;")
}
func MarshalBool(value bool) []byte {
if value {
return []byte("b:1;")
}
return []byte("b:0;")
}
func MarshalNumber(value interface{}) []byte {
var val string
isFloat := false
switch value.(type) {
default:
val = "0"
case int, int8, int16, int32, int64, uint, uint8, uint16, uint32, uint64:
val, _ = NumericalToString(value)
case float32, float64:
val, _ = NumericalToString(value)
isFloat = true
}
if isFloat {
return []byte("d:" + val + ";")
} else {
return []byte("i:" + val + ";")
}
}
func MarshalString(value string) []byte {
return []byte(fmt.Sprintf("s:%d:\"%s\";", len(value), value))
}
func MarshalMap(value interface{}) ([]byte, error) {
s := reflect.ValueOf(value)
mapKeys := s.MapKeys()
sort.Slice(mapKeys, func(i, j int) bool {
return LessValue(mapKeys[i], mapKeys[j])
})
var buffer bytes.Buffer
for _, mapKey := range mapKeys {
m, err := Marshal(mapKey.Interface())
if err != nil {
return nil, err
}
buffer.Write(m)
m, err = Marshal(s.MapIndex(mapKey).Interface())
if err != nil {
return nil, err
}
buffer.Write(m)
}
return []byte(fmt.Sprintf("a:%d:{%s}", s.Len(), buffer.String())), nil
}
func MarshalSlice(value interface{}) ([]byte, error) {
s := reflect.ValueOf(value)
var buffer bytes.Buffer

最低0.47元/天 解锁文章
1572





