From 10e042454ce8c840f5c3625ae593f88d17efbac8 Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Jul 2019 15:41:06 +0800 Subject: [PATCH 1/2] fix issue in bit type conversion for mssql in gdb --- g/database/gdb/gdb_structure.go | 23 +++++++++++------------ geg/database/gdb/mssql/config.toml | 8 ++++++++ geg/database/gdb/mssql/gdb_all.go | 14 ++++++++++++++ 3 files changed, 33 insertions(+), 12 deletions(-) create mode 100644 geg/database/gdb/mssql/config.toml create mode 100644 geg/database/gdb/mssql/gdb_all.go diff --git a/g/database/gdb/gdb_structure.go b/g/database/gdb/gdb_structure.go index f88a7dcb9..e1c81f1ea 100644 --- a/g/database/gdb/gdb_structure.go +++ b/g/database/gdb/gdb_structure.go @@ -8,20 +8,19 @@ package gdb import ( "fmt" + "strings" + "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/util/gconv" - "strings" ) -/* -// 同步数据库表结构到内存中 -func (bs *dbBase) syncTableStructure() { - bs.tables = make(map[string]map[string]string) - for _, table := range bs.db.getTables() { - bs.tables[table], _ = bs.db.getTableFields(table) - } -} -*/ +//// 同步数据库表结构到内存中 +//func (bs *dbBase) syncTableStructure() { +// bs.tables = make(map[string]map[string]string) +// for _, table := range bs.db.getTables() { +// bs.tables[table], _ = bs.db.getTableFields(table) +// } +//} // 字段类型转换,将数据库字段类型转换为golang变量类型 func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interface{} { @@ -31,7 +30,7 @@ func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interfa case "binary", "varbinary", "blob", "tinyblob", "mediumblob", "longblob": return gconv.Bytes(fieldValue) - case "bit", "int", "tinyint", "small_int", "medium_int": + case "int", "tinyint", "small_int", "medium_int": return gconv.Int(fieldValue) case "big_int": @@ -40,7 +39,7 @@ func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interfa case "float", "double", "decimal": return gconv.Float64(fieldValue) - case "bool": + case "bit", "bool": return gconv.Bool(fieldValue) default: diff --git a/geg/database/gdb/mssql/config.toml b/geg/database/gdb/mssql/config.toml new file mode 100644 index 000000000..8e44ef003 --- /dev/null +++ b/geg/database/gdb/mssql/config.toml @@ -0,0 +1,8 @@ + +[database] + type = "mssql" + host = "116.255.140.92" + port = "1451" + user = "sa" + pass = "eno@123" + name = "frpc" diff --git a/geg/database/gdb/mssql/gdb_all.go b/geg/database/gdb/mssql/gdb_all.go new file mode 100644 index 000000000..ad4c5806d --- /dev/null +++ b/geg/database/gdb/mssql/gdb_all.go @@ -0,0 +1,14 @@ +package main + +import ( + "fmt" + + //_ "github.com/denisenkom/go-mssqldb" + "github.com/gogf/gf/g" +) + +func main() { + r, err := g.DB().GetAll(`SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 * FROM KF_PatInfo_Emergency WHERE Report_BZ = 1 AND Examine_BZ = 0 ) as TMP1_ ) as TMP2_`) + fmt.Println(err) + g.Dump(r.ToList()) +} From a95624ab19c5be2c75ee1356dea62f7b4707b59c Mon Sep 17 00:00:00 2001 From: John Date: Thu, 11 Jul 2019 18:58:31 +0800 Subject: [PATCH 2/2] add big-endian support for gbinary; improve gdb for bit type support --- g/database/gdb/gdb_structure.go | 18 +- g/encoding/gbinary/gbinary.go | 281 +++--------------- g/encoding/gbinary/gbinary_be.go | 278 +++++++++++++++++ g/encoding/gbinary/gbinary_bits.go | 72 +++++ g/encoding/gbinary/gbinary_func.go | 7 + g/encoding/gbinary/gbinary_le.go | 278 +++++++++++++++++ g/encoding/gbinary/gbinary_z_be_test.go | 84 ++++++ g/encoding/gbinary/gbinary_z_le_test.go | 84 ++++++ .../{gbinary_test.go => gbinary_z_test.go} | 27 +- geg/database/gdb/mssql/config.toml | 2 +- geg/database/gdb/mssql/gdb_all.go | 4 +- geg/database/gdb/mysql/gdb_all.go | 21 ++ geg/other/test.go | 43 +-- 13 files changed, 905 insertions(+), 294 deletions(-) create mode 100644 g/encoding/gbinary/gbinary_be.go create mode 100644 g/encoding/gbinary/gbinary_bits.go create mode 100644 g/encoding/gbinary/gbinary_func.go create mode 100644 g/encoding/gbinary/gbinary_le.go create mode 100644 g/encoding/gbinary/gbinary_z_be_test.go create mode 100644 g/encoding/gbinary/gbinary_z_le_test.go rename g/encoding/gbinary/{gbinary_test.go => gbinary_z_test.go} (96%) create mode 100644 geg/database/gdb/mysql/gdb_all.go diff --git a/g/database/gdb/gdb_structure.go b/g/database/gdb/gdb_structure.go index e1c81f1ea..03dbdb0a4 100644 --- a/g/database/gdb/gdb_structure.go +++ b/g/database/gdb/gdb_structure.go @@ -10,6 +10,8 @@ import ( "fmt" "strings" + "github.com/gogf/gf/g/encoding/gbinary" + "github.com/gogf/gf/g/text/gregex" "github.com/gogf/gf/g/util/gconv" ) @@ -39,7 +41,21 @@ func (bs *dbBase) convertValue(fieldValue interface{}, fieldType string) interfa case "float", "double", "decimal": return gconv.Float64(fieldValue) - case "bit", "bool": + case "bit": + s := gconv.String(fieldValue) + // 这里的字符串判断是为兼容不同的数据库类型,如: mssql + if strings.EqualFold(s, "true") { + return 1 + } + if strings.EqualFold(s, "false") { + return 0 + } + if b, ok := fieldValue.([]byte); ok { + return gbinary.BeDecodeToInt64(b) + } + return gconv.Int(fieldValue) + + case "bool": return gconv.Bool(fieldValue) default: diff --git a/g/encoding/gbinary/gbinary.go b/g/encoding/gbinary/gbinary.go index 8cd429c5a..2bdde6b08 100644 --- a/g/encoding/gbinary/gbinary.go +++ b/g/encoding/gbinary/gbinary.go @@ -6,340 +6,129 @@ // Package gbinary provides useful API for handling binary/bytes data. // -// 注意gbinary模块统一使用LittleEndian进行编码。 +// 注意gbinary模块默认使用LittleEndian进行编码。 package gbinary -import ( - "bytes" - "encoding/binary" - "fmt" - "math" -) - -// 二进制位(0|1) -type Bit int8 - -// 针对基本类型进行二进制打包,支持的基本数据类型包括:int/8/16/32/64、uint/8/16/32/64、float32/64、bool、string、[]byte -// 其他未知类型使用 fmt.Sprintf("%v", value) 转换为字符串之后处理 -func Encode(vs ...interface{}) []byte { - buf := new(bytes.Buffer) - for i := 0; i < len(vs); i++ { - if vs[i] == nil { - return buf.Bytes() - } - - switch value := vs[i].(type) { - case int: - buf.Write(EncodeInt(value)) - case int8: - buf.Write(EncodeInt8(value)) - case int16: - buf.Write(EncodeInt16(value)) - case int32: - buf.Write(EncodeInt32(value)) - case int64: - buf.Write(EncodeInt64(value)) - case uint: - buf.Write(EncodeUint(value)) - case uint8: - buf.Write(EncodeUint8(value)) - case uint16: - buf.Write(EncodeUint16(value)) - case uint32: - buf.Write(EncodeUint32(value)) - case uint64: - buf.Write(EncodeUint64(value)) - case bool: - buf.Write(EncodeBool(value)) - case string: - buf.Write(EncodeString(value)) - case []byte: - buf.Write(value) - case float32: - buf.Write(EncodeFloat32(value)) - case float64: - buf.Write(EncodeFloat64(value)) - default: - if err := binary.Write(buf, binary.LittleEndian, value); err != nil { - buf.Write(EncodeString(fmt.Sprintf("%v", value))) - } - } - } - return buf.Bytes() +func Encode(values ...interface{}) []byte { + return LeEncode(values...) } -// 将变量转换为二进制[]byte,并指定固定的[]byte长度返回,长度单位为字节(byte); -// 如果转换的二进制长度超过指定长度,那么进行截断处理 -func EncodeByLength(length int, vs ...interface{}) []byte { - b := Encode(vs...) - if len(b) < length { - b = append(b, make([]byte, length-len(b))...) - } else if len(b) > length { - b = b[0:length] - } - return b +func EncodeByLength(length int, values ...interface{}) []byte { + return LeEncodeByLength(length, values...) } -// 整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,以便确定解析的[]byte长度, -// 例如:int8/16/32/64、uint8/16/32/64、float32/64等等 -func Decode(b []byte, vs ...interface{}) error { - buf := bytes.NewBuffer(b) - for i := 0; i < len(vs); i++ { - err := binary.Read(buf, binary.LittleEndian, vs[i]) - if err != nil { - return err - } - } - return nil +func Decode(b []byte, values ...interface{}) error { + return LeDecode(b, values...) } func EncodeString(s string) []byte { - return []byte(s) + return LeEncodeString(s) } func DecodeToString(b []byte) string { - return string(b) + return LeDecodeToString(b) } func EncodeBool(b bool) []byte { - if b == true { - return []byte{1} - } else { - return []byte{0} - } + return LeEncodeBool(b) } -// 自动识别int类型长度,转换为[]byte func EncodeInt(i int) []byte { - if i <= math.MaxInt8 { - return EncodeInt8(int8(i)) - } else if i <= math.MaxInt16 { - return EncodeInt16(int16(i)) - } else if i <= math.MaxInt32 { - return EncodeInt32(int32(i)) - } else { - return EncodeInt64(int64(i)) - } + return LeEncodeInt(i) } -// 自动识别uint类型长度,转换为[]byte func EncodeUint(i uint) []byte { - if i <= math.MaxUint8 { - return EncodeUint8(uint8(i)) - } else if i <= math.MaxUint16 { - return EncodeUint16(uint16(i)) - } else if i <= math.MaxUint32 { - return EncodeUint32(uint32(i)) - } else { - return EncodeUint64(uint64(i)) - } + return LeEncodeUint(i) } func EncodeInt8(i int8) []byte { - return []byte{byte(i)} + return LeEncodeInt8(i) } func EncodeUint8(i uint8) []byte { - return []byte{byte(i)} + return LeEncodeUint8(i) } func EncodeInt16(i int16) []byte { - bytes := make([]byte, 2) - binary.LittleEndian.PutUint16(bytes, uint16(i)) - return bytes + return LeEncodeInt16(i) } func EncodeUint16(i uint16) []byte { - bytes := make([]byte, 2) - binary.LittleEndian.PutUint16(bytes, i) - return bytes + return LeEncodeUint16(i) } func EncodeInt32(i int32) []byte { - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, uint32(i)) - return bytes + return LeEncodeInt32(i) } func EncodeUint32(i uint32) []byte { - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, i) - return bytes + return LeEncodeUint32(i) } func EncodeInt64(i int64) []byte { - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, uint64(i)) - return bytes + return LeEncodeInt64(i) } func EncodeUint64(i uint64) []byte { - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, i) - return bytes + return LeEncodeUint64(i) } func EncodeFloat32(f float32) []byte { - bits := math.Float32bits(f) - bytes := make([]byte, 4) - binary.LittleEndian.PutUint32(bytes, bits) - return bytes + return LeEncodeFloat32(f) } func EncodeFloat64(f float64) []byte { - bits := math.Float64bits(f) - bytes := make([]byte, 8) - binary.LittleEndian.PutUint64(bytes, bits) - return bytes + return LeEncodeFloat64(f) } -// 当b位数不够时,进行高位补0 -func fillUpSize(b []byte, l int) []byte { - if len(b) >= l { - return b - } - c := make([]byte, 0) - c = append(c, b...) - for i := 0; i < l-len(b); i++ { - c = append(c, 0x00) - } - return c -} - -// 将二进制解析为int类型,根据[]byte的长度进行自动转换. -// 注意内部使用的是uint*,使用int会造成位丢失。 func DecodeToInt(b []byte) int { - if len(b) < 2 { - return int(DecodeToUint8(b)) - } else if len(b) < 3 { - return int(DecodeToUint16(b)) - } else if len(b) < 5 { - return int(DecodeToUint32(b)) - } else { - return int(DecodeToUint64(b)) - } + return LeDecodeToInt(b) } -// 将二进制解析为uint类型,根据[]byte的长度进行自动转换 func DecodeToUint(b []byte) uint { - if len(b) < 2 { - return uint(DecodeToUint8(b)) - } else if len(b) < 3 { - return uint(DecodeToUint16(b)) - } else if len(b) < 5 { - return uint(DecodeToUint32(b)) - } else { - return uint(DecodeToUint64(b)) - } + return LeDecodeToUint(b) } -// 将二进制解析为bool类型,识别标准是判断二进制中数值是否都为0,或者为空 func DecodeToBool(b []byte) bool { - if len(b) == 0 { - return false - } - if bytes.Compare(b, make([]byte, len(b))) == 0 { - return false - } - return true + return LeDecodeToBool(b) } func DecodeToInt8(b []byte) int8 { - return int8(b[0]) + return LeDecodeToInt8(b) } func DecodeToUint8(b []byte) uint8 { - return uint8(b[0]) + return LeDecodeToUint8(b) } func DecodeToInt16(b []byte) int16 { - return int16(binary.LittleEndian.Uint16(fillUpSize(b, 2))) + return LeDecodeToInt16(b) } func DecodeToUint16(b []byte) uint16 { - return binary.LittleEndian.Uint16(fillUpSize(b, 2)) + return LeDecodeToUint16(b) } func DecodeToInt32(b []byte) int32 { - return int32(binary.LittleEndian.Uint32(fillUpSize(b, 4))) + return LeDecodeToInt32(b) } func DecodeToUint32(b []byte) uint32 { - return binary.LittleEndian.Uint32(fillUpSize(b, 4)) + return LeDecodeToUint32(b) } func DecodeToInt64(b []byte) int64 { - return int64(binary.LittleEndian.Uint64(fillUpSize(b, 8))) + return LeDecodeToInt64(b) } func DecodeToUint64(b []byte) uint64 { - return binary.LittleEndian.Uint64(fillUpSize(b, 8)) + return LeDecodeToUint64(b) } func DecodeToFloat32(b []byte) float32 { - return math.Float32frombits(binary.LittleEndian.Uint32(fillUpSize(b, 4))) + return LeDecodeToFloat32(b) } func DecodeToFloat64(b []byte) float64 { - return math.Float64frombits(binary.LittleEndian.Uint64(fillUpSize(b, 8))) -} - -// 默认编码 -func EncodeBits(bits []Bit, i int, l int) []Bit { - return EncodeBitsWithUint(bits, uint(i), l) -} - -// 将ui按位合并到bits数组中,并占length长度位(注意:uis数组中存放的是二进制的0|1数字) -func EncodeBitsWithUint(bits []Bit, ui uint, l int) []Bit { - a := make([]Bit, l) - for i := l - 1; i >= 0; i-- { - a[i] = Bit(ui & 1) - ui >>= 1 - } - if bits != nil { - return append(bits, a...) - } else { - return a - } -} - -// 将bits转换为[]byte,从左至右进行编码,不足1 byte按0往末尾补充 -func EncodeBitsToBytes(bits []Bit) []byte { - if len(bits)%8 != 0 { - for i := 0; i < len(bits)%8; i++ { - bits = append(bits, 0) - } - } - b := make([]byte, 0) - for i := 0; i < len(bits); i += 8 { - b = append(b, byte(DecodeBitsToUint(bits[i:i+8]))) - } - return b -} - -// 解析为int -func DecodeBits(bits []Bit) int { - v := int(0) - for _, i := range bits { - v = v<<1 | int(i) - } - return v -} - -// 解析为uint -func DecodeBitsToUint(bits []Bit) uint { - v := uint(0) - for _, i := range bits { - v = v<<1 | uint(i) - } - return v -} - -// 解析[]byte为字位数组[]uint8 -func DecodeBytesToBits(bs []byte) []Bit { - bits := make([]Bit, 0) - for _, b := range bs { - bits = EncodeBitsWithUint(bits, uint(b), 8) - } - return bits + return LeDecodeToFloat64(b) } diff --git a/g/encoding/gbinary/gbinary_be.go b/g/encoding/gbinary/gbinary_be.go new file mode 100644 index 000000000..41b890c6e --- /dev/null +++ b/g/encoding/gbinary/gbinary_be.go @@ -0,0 +1,278 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary + +import ( + "bytes" + "encoding/binary" + "fmt" + "math" +) + +// 针对基本类型进行二进制打包,支持的基本数据类型包括: +// int/8/16/32/64、uint/8/16/32/64、float32/64、bool、string、[]byte。 +// 其他未知类型使用 fmt.Sprintf("%v", value) 转换为字符串之后处理。 +func BeEncode(values ...interface{}) []byte { + buf := new(bytes.Buffer) + for i := 0; i < len(values); i++ { + if values[i] == nil { + return buf.Bytes() + } + + switch value := values[i].(type) { + case int: + buf.Write(BeEncodeInt(value)) + case int8: + buf.Write(BeEncodeInt8(value)) + case int16: + buf.Write(BeEncodeInt16(value)) + case int32: + buf.Write(BeEncodeInt32(value)) + case int64: + buf.Write(BeEncodeInt64(value)) + case uint: + buf.Write(BeEncodeUint(value)) + case uint8: + buf.Write(BeEncodeUint8(value)) + case uint16: + buf.Write(BeEncodeUint16(value)) + case uint32: + buf.Write(BeEncodeUint32(value)) + case uint64: + buf.Write(BeEncodeUint64(value)) + case bool: + buf.Write(BeEncodeBool(value)) + case string: + buf.Write(BeEncodeString(value)) + case []byte: + buf.Write(value) + case float32: + buf.Write(BeEncodeFloat32(value)) + case float64: + buf.Write(BeEncodeFloat64(value)) + default: + if err := binary.Write(buf, binary.BigEndian, value); err != nil { + buf.Write(BeEncodeString(fmt.Sprintf("%v", value))) + } + } + } + return buf.Bytes() +} + +// 将变量转换为二进制[]byte,并指定固定的[]byte长度返回,长度单位为字节(byte); +// 如果转换的二进制长度超过指定长度,那么进行截断处理 +func BeEncodeByLength(length int, values ...interface{}) []byte { + b := BeEncode(values...) + if len(b) < length { + b = append(b, make([]byte, length-len(b))...) + } else if len(b) > length { + b = b[0:length] + } + return b +} + +// 整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,以便确定解析的[]byte长度, +// 例如:int8/16/32/64、uint8/16/32/64、float32/64等等 +func BeDecode(b []byte, values ...interface{}) error { + buf := bytes.NewBuffer(b) + for i := 0; i < len(values); i++ { + err := binary.Read(buf, binary.BigEndian, values[i]) + if err != nil { + return err + } + } + return nil +} + +func BeEncodeString(s string) []byte { + return []byte(s) +} + +func BeDecodeToString(b []byte) string { + return string(b) +} + +func BeEncodeBool(b bool) []byte { + if b == true { + return []byte{1} + } else { + return []byte{0} + } +} + +// 自动识别int类型长度,转换为[]byte +func BeEncodeInt(i int) []byte { + if i <= math.MaxInt8 { + return BeEncodeInt8(int8(i)) + } else if i <= math.MaxInt16 { + return BeEncodeInt16(int16(i)) + } else if i <= math.MaxInt32 { + return BeEncodeInt32(int32(i)) + } else { + return BeEncodeInt64(int64(i)) + } +} + +// 自动识别uint类型长度,转换为[]byte +func BeEncodeUint(i uint) []byte { + if i <= math.MaxUint8 { + return BeEncodeUint8(uint8(i)) + } else if i <= math.MaxUint16 { + return BeEncodeUint16(uint16(i)) + } else if i <= math.MaxUint32 { + return BeEncodeUint32(uint32(i)) + } else { + return BeEncodeUint64(uint64(i)) + } +} + +func BeEncodeInt8(i int8) []byte { + return []byte{byte(i)} +} + +func BeEncodeUint8(i uint8) []byte { + return []byte{byte(i)} +} + +func BeEncodeInt16(i int16) []byte { + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, uint16(i)) + return b +} + +func BeEncodeUint16(i uint16) []byte { + b := make([]byte, 2) + binary.BigEndian.PutUint16(b, i) + return b +} + +func BeEncodeInt32(i int32) []byte { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, uint32(i)) + return b +} + +func BeEncodeUint32(i uint32) []byte { + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, i) + return b +} + +func BeEncodeInt64(i int64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, uint64(i)) + return b +} + +func BeEncodeUint64(i uint64) []byte { + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, i) + return b +} + +func BeEncodeFloat32(f float32) []byte { + bits := math.Float32bits(f) + b := make([]byte, 4) + binary.BigEndian.PutUint32(b, bits) + return b +} + +func BeEncodeFloat64(f float64) []byte { + bits := math.Float64bits(f) + b := make([]byte, 8) + binary.BigEndian.PutUint64(b, bits) + return b +} + +// 将二进制解析为int类型,根据[]byte的长度进行自动转换. +// 注意内部使用的是uint*,使用int会造成位丢失。 +func BeDecodeToInt(b []byte) int { + if len(b) < 2 { + return int(BeDecodeToUint8(b)) + } else if len(b) < 3 { + return int(BeDecodeToUint16(b)) + } else if len(b) < 5 { + return int(BeDecodeToUint32(b)) + } else { + return int(BeDecodeToUint64(b)) + } +} + +// 将二进制解析为uint类型,根据[]byte的长度进行自动转换 +func BeDecodeToUint(b []byte) uint { + if len(b) < 2 { + return uint(BeDecodeToUint8(b)) + } else if len(b) < 3 { + return uint(BeDecodeToUint16(b)) + } else if len(b) < 5 { + return uint(BeDecodeToUint32(b)) + } else { + return uint(BeDecodeToUint64(b)) + } +} + +// 将二进制解析为bool类型,识别标准是判断二进制中数值是否都为0,或者为空。 +func BeDecodeToBool(b []byte) bool { + if len(b) == 0 { + return false + } + if bytes.Compare(b, make([]byte, len(b))) == 0 { + return false + } + return true +} + +func BeDecodeToInt8(b []byte) int8 { + return int8(b[0]) +} + +func BeDecodeToUint8(b []byte) uint8 { + return uint8(b[0]) +} + +func BeDecodeToInt16(b []byte) int16 { + return int16(binary.BigEndian.Uint16(BeFillUpSize(b, 2))) +} + +func BeDecodeToUint16(b []byte) uint16 { + return binary.BigEndian.Uint16(BeFillUpSize(b, 2)) +} + +func BeDecodeToInt32(b []byte) int32 { + return int32(binary.BigEndian.Uint32(BeFillUpSize(b, 4))) +} + +func BeDecodeToUint32(b []byte) uint32 { + return binary.BigEndian.Uint32(BeFillUpSize(b, 4)) +} + +func BeDecodeToInt64(b []byte) int64 { + return int64(binary.BigEndian.Uint64(BeFillUpSize(b, 8))) +} + +func BeDecodeToUint64(b []byte) uint64 { + return binary.BigEndian.Uint64(BeFillUpSize(b, 8)) +} + +func BeDecodeToFloat32(b []byte) float32 { + return math.Float32frombits(binary.BigEndian.Uint32(BeFillUpSize(b, 4))) +} + +func BeDecodeToFloat64(b []byte) float64 { + return math.Float64frombits(binary.BigEndian.Uint64(BeFillUpSize(b, 8))) +} + +// 当b位数不够时,进行低位补0。 +// 注意这里为了不影响原有输入参数,是采用的值复制设计。 +func BeFillUpSize(b []byte, l int) []byte { + if len(b) >= l { + return b[:l] + } + c := make([]byte, l) + copy(c[l-len(b):], b) + return c +} diff --git a/g/encoding/gbinary/gbinary_bits.go b/g/encoding/gbinary/gbinary_bits.go new file mode 100644 index 000000000..a61b5fdf7 --- /dev/null +++ b/g/encoding/gbinary/gbinary_bits.go @@ -0,0 +1,72 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary + +// 实验特性 + +// 二进制位(0|1) +type Bit int8 + +// 默认编码 +func EncodeBits(bits []Bit, i int, l int) []Bit { + return EncodeBitsWithUint(bits, uint(i), l) +} + +// 将ui按位合并到bits数组中,并占length长度位(注意:uis数组中存放的是二进制的0|1数字) +func EncodeBitsWithUint(bits []Bit, ui uint, l int) []Bit { + a := make([]Bit, l) + for i := l - 1; i >= 0; i-- { + a[i] = Bit(ui & 1) + ui >>= 1 + } + if bits != nil { + return append(bits, a...) + } else { + return a + } +} + +// 将bits转换为[]byte,从左至右进行编码,不足1 byte按0往末尾补充 +func EncodeBitsToBytes(bits []Bit) []byte { + if len(bits)%8 != 0 { + for i := 0; i < len(bits)%8; i++ { + bits = append(bits, 0) + } + } + b := make([]byte, 0) + for i := 0; i < len(bits); i += 8 { + b = append(b, byte(DecodeBitsToUint(bits[i:i+8]))) + } + return b +} + +// 解析为int +func DecodeBits(bits []Bit) int { + v := int(0) + for _, i := range bits { + v = v<<1 | int(i) + } + return v +} + +// 解析为uint +func DecodeBitsToUint(bits []Bit) uint { + v := uint(0) + for _, i := range bits { + v = v<<1 | uint(i) + } + return v +} + +// 解析[]byte为字位数组[]uint8 +func DecodeBytesToBits(bs []byte) []Bit { + bits := make([]Bit, 0) + for _, b := range bs { + bits = EncodeBitsWithUint(bits, uint(b), 8) + } + return bits +} diff --git a/g/encoding/gbinary/gbinary_func.go b/g/encoding/gbinary/gbinary_func.go new file mode 100644 index 000000000..8fd332e98 --- /dev/null +++ b/g/encoding/gbinary/gbinary_func.go @@ -0,0 +1,7 @@ +// Copyright 2019 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary diff --git a/g/encoding/gbinary/gbinary_le.go b/g/encoding/gbinary/gbinary_le.go new file mode 100644 index 000000000..2b236bfa9 --- /dev/null +++ b/g/encoding/gbinary/gbinary_le.go @@ -0,0 +1,278 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary + +import ( + "bytes" + "encoding/binary" + "fmt" + "math" +) + +// 针对基本类型进行二进制打包,支持的基本数据类型包括: +// int/8/16/32/64、uint/8/16/32/64、float32/64、bool、string、[]byte。 +// 其他未知类型使用 fmt.Sprintf("%v", value) 转换为字符串之后处理。 +func LeEncode(values ...interface{}) []byte { + buf := new(bytes.Buffer) + for i := 0; i < len(values); i++ { + if values[i] == nil { + return buf.Bytes() + } + + switch value := values[i].(type) { + case int: + buf.Write(LeEncodeInt(value)) + case int8: + buf.Write(LeEncodeInt8(value)) + case int16: + buf.Write(LeEncodeInt16(value)) + case int32: + buf.Write(LeEncodeInt32(value)) + case int64: + buf.Write(LeEncodeInt64(value)) + case uint: + buf.Write(LeEncodeUint(value)) + case uint8: + buf.Write(LeEncodeUint8(value)) + case uint16: + buf.Write(LeEncodeUint16(value)) + case uint32: + buf.Write(LeEncodeUint32(value)) + case uint64: + buf.Write(LeEncodeUint64(value)) + case bool: + buf.Write(LeEncodeBool(value)) + case string: + buf.Write(LeEncodeString(value)) + case []byte: + buf.Write(value) + case float32: + buf.Write(LeEncodeFloat32(value)) + case float64: + buf.Write(LeEncodeFloat64(value)) + default: + if err := binary.Write(buf, binary.LittleEndian, value); err != nil { + buf.Write(LeEncodeString(fmt.Sprintf("%v", value))) + } + } + } + return buf.Bytes() +} + +// 将变量转换为二进制[]byte,并指定固定的[]byte长度返回,长度单位为字节(byte); +// 如果转换的二进制长度超过指定长度,那么进行截断处理 +func LeEncodeByLength(length int, values ...interface{}) []byte { + b := LeEncode(values...) + if len(b) < length { + b = append(b, make([]byte, length-len(b))...) + } else if len(b) > length { + b = b[0:length] + } + return b +} + +// 整形二进制解包,注意第二个及其后参数为字长确定的整形变量的指针地址,以便确定解析的[]byte长度, +// 例如:int8/16/32/64、uint8/16/32/64、float32/64等等 +func LeDecode(b []byte, values ...interface{}) error { + buf := bytes.NewBuffer(b) + for i := 0; i < len(values); i++ { + err := binary.Read(buf, binary.LittleEndian, values[i]) + if err != nil { + return err + } + } + return nil +} + +func LeEncodeString(s string) []byte { + return []byte(s) +} + +func LeDecodeToString(b []byte) string { + return string(b) +} + +func LeEncodeBool(b bool) []byte { + if b == true { + return []byte{1} + } else { + return []byte{0} + } +} + +// 自动识别int类型长度,转换为[]byte +func LeEncodeInt(i int) []byte { + if i <= math.MaxInt8 { + return EncodeInt8(int8(i)) + } else if i <= math.MaxInt16 { + return EncodeInt16(int16(i)) + } else if i <= math.MaxInt32 { + return EncodeInt32(int32(i)) + } else { + return EncodeInt64(int64(i)) + } +} + +// 自动识别uint类型长度,转换为[]byte +func LeEncodeUint(i uint) []byte { + if i <= math.MaxUint8 { + return EncodeUint8(uint8(i)) + } else if i <= math.MaxUint16 { + return EncodeUint16(uint16(i)) + } else if i <= math.MaxUint32 { + return EncodeUint32(uint32(i)) + } else { + return EncodeUint64(uint64(i)) + } +} + +func LeEncodeInt8(i int8) []byte { + return []byte{byte(i)} +} + +func LeEncodeUint8(i uint8) []byte { + return []byte{byte(i)} +} + +func LeEncodeInt16(i int16) []byte { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, uint16(i)) + return b +} + +func LeEncodeUint16(i uint16) []byte { + b := make([]byte, 2) + binary.LittleEndian.PutUint16(b, i) + return b +} + +func LeEncodeInt32(i int32) []byte { + b := make([]byte, 4) + binary.LittleEndian.PutUint32(b, uint32(i)) + return b +} + +func LeEncodeUint32(i uint32) []byte { + b := make([]byte, 4) + binary.LittleEndian.PutUint32(b, i) + return b +} + +func LeEncodeInt64(i int64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, uint64(i)) + return b +} + +func LeEncodeUint64(i uint64) []byte { + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, i) + return b +} + +func LeEncodeFloat32(f float32) []byte { + bits := math.Float32bits(f) + b := make([]byte, 4) + binary.LittleEndian.PutUint32(b, bits) + return b +} + +func LeEncodeFloat64(f float64) []byte { + bits := math.Float64bits(f) + b := make([]byte, 8) + binary.LittleEndian.PutUint64(b, bits) + return b +} + +// 将二进制解析为int类型,根据[]byte的长度进行自动转换. +// 注意内部使用的是uint*,使用int会造成位丢失。 +func LeDecodeToInt(b []byte) int { + if len(b) < 2 { + return int(LeDecodeToUint8(b)) + } else if len(b) < 3 { + return int(LeDecodeToUint16(b)) + } else if len(b) < 5 { + return int(LeDecodeToUint32(b)) + } else { + return int(LeDecodeToUint64(b)) + } +} + +// 将二进制解析为uint类型,根据[]byte的长度进行自动转换 +func LeDecodeToUint(b []byte) uint { + if len(b) < 2 { + return uint(LeDecodeToUint8(b)) + } else if len(b) < 3 { + return uint(LeDecodeToUint16(b)) + } else if len(b) < 5 { + return uint(LeDecodeToUint32(b)) + } else { + return uint(LeDecodeToUint64(b)) + } +} + +// 将二进制解析为bool类型,识别标准是判断二进制中数值是否都为0,或者为空。 +func LeDecodeToBool(b []byte) bool { + if len(b) == 0 { + return false + } + if bytes.Compare(b, make([]byte, len(b))) == 0 { + return false + } + return true +} + +func LeDecodeToInt8(b []byte) int8 { + return int8(b[0]) +} + +func LeDecodeToUint8(b []byte) uint8 { + return uint8(b[0]) +} + +func LeDecodeToInt16(b []byte) int16 { + return int16(binary.LittleEndian.Uint16(LeFillUpSize(b, 2))) +} + +func LeDecodeToUint16(b []byte) uint16 { + return binary.LittleEndian.Uint16(LeFillUpSize(b, 2)) +} + +func LeDecodeToInt32(b []byte) int32 { + return int32(binary.LittleEndian.Uint32(LeFillUpSize(b, 4))) +} + +func LeDecodeToUint32(b []byte) uint32 { + return binary.LittleEndian.Uint32(LeFillUpSize(b, 4)) +} + +func LeDecodeToInt64(b []byte) int64 { + return int64(binary.LittleEndian.Uint64(LeFillUpSize(b, 8))) +} + +func LeDecodeToUint64(b []byte) uint64 { + return binary.LittleEndian.Uint64(LeFillUpSize(b, 8)) +} + +func LeDecodeToFloat32(b []byte) float32 { + return math.Float32frombits(binary.LittleEndian.Uint32(LeFillUpSize(b, 4))) +} + +func LeDecodeToFloat64(b []byte) float64 { + return math.Float64frombits(binary.LittleEndian.Uint64(LeFillUpSize(b, 8))) +} + +// 当b位数不够时,进行高位补0。 +// 注意这里为了不影响原有输入参数,是采用的值复制设计。 +func LeFillUpSize(b []byte, l int) []byte { + if len(b) >= l { + return b[:l] + } + c := make([]byte, l) + copy(c, b) + return c +} diff --git a/g/encoding/gbinary/gbinary_z_be_test.go b/g/encoding/gbinary/gbinary_z_be_test.go new file mode 100644 index 000000000..4eccc3324 --- /dev/null +++ b/g/encoding/gbinary/gbinary_z_be_test.go @@ -0,0 +1,84 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary_test + +import ( + "testing" + + "github.com/gogf/gf/g/encoding/gbinary" + "github.com/gogf/gf/g/test/gtest" +) + +func Test_BeEncodeAndBeDecode(t *testing.T) { + for k, v := range testData { + ve := gbinary.BeEncode(v) + ve1 := gbinary.BeEncodeByLength(len(ve), v) + + //t.Logf("%s:%v, encoded:%v\n", k, v, ve) + switch v.(type) { + case int: + gtest.Assert(gbinary.BeDecodeToInt(ve), v) + gtest.Assert(gbinary.BeDecodeToInt(ve1), v) + case int8: + gtest.Assert(gbinary.BeDecodeToInt8(ve), v) + gtest.Assert(gbinary.BeDecodeToInt8(ve1), v) + case int16: + gtest.Assert(gbinary.BeDecodeToInt16(ve), v) + gtest.Assert(gbinary.BeDecodeToInt16(ve1), v) + case int32: + gtest.Assert(gbinary.BeDecodeToInt32(ve), v) + gtest.Assert(gbinary.BeDecodeToInt32(ve1), v) + case int64: + gtest.Assert(gbinary.BeDecodeToInt64(ve), v) + gtest.Assert(gbinary.BeDecodeToInt64(ve1), v) + case uint: + gtest.Assert(gbinary.BeDecodeToUint(ve), v) + gtest.Assert(gbinary.BeDecodeToUint(ve1), v) + case uint8: + gtest.Assert(gbinary.BeDecodeToUint8(ve), v) + gtest.Assert(gbinary.BeDecodeToUint8(ve1), v) + case uint16: + gtest.Assert(gbinary.BeDecodeToUint16(ve1), v) + gtest.Assert(gbinary.BeDecodeToUint16(ve), v) + case uint32: + gtest.Assert(gbinary.BeDecodeToUint32(ve1), v) + gtest.Assert(gbinary.BeDecodeToUint32(ve), v) + case uint64: + gtest.Assert(gbinary.BeDecodeToUint64(ve), v) + gtest.Assert(gbinary.BeDecodeToUint64(ve1), v) + case bool: + gtest.Assert(gbinary.BeDecodeToBool(ve), v) + gtest.Assert(gbinary.BeDecodeToBool(ve1), v) + case string: + gtest.Assert(gbinary.BeDecodeToString(ve), v) + gtest.Assert(gbinary.BeDecodeToString(ve1), v) + case float32: + gtest.Assert(gbinary.BeDecodeToFloat32(ve), v) + gtest.Assert(gbinary.BeDecodeToFloat32(ve1), v) + case float64: + gtest.Assert(gbinary.BeDecodeToFloat64(ve), v) + gtest.Assert(gbinary.BeDecodeToFloat64(ve1), v) + default: + if v == nil { + continue + } + res := make([]byte, len(ve)) + err := gbinary.BeDecode(ve, res) + if err != nil { + t.Errorf("test data: %s, %v, error:%v", k, v, err) + } + gtest.Assert(res, v) + } + } +} + +func Test_BeEncodeStruct(t *testing.T) { + user := User{"wenzi1", 999, "www.baidu.com"} + ve := gbinary.BeEncode(user) + s := gbinary.BeDecodeToString(ve) + gtest.Assert(string(s), s) +} diff --git a/g/encoding/gbinary/gbinary_z_le_test.go b/g/encoding/gbinary/gbinary_z_le_test.go new file mode 100644 index 000000000..f5c81ff57 --- /dev/null +++ b/g/encoding/gbinary/gbinary_z_le_test.go @@ -0,0 +1,84 @@ +// Copyright 2017 gf Author(https://github.com/gogf/gf). All Rights Reserved. +// +// This Source Code Form is subject to the terms of the MIT License. +// If a copy of the MIT was not distributed with this file, +// You can obtain one at https://github.com/gogf/gf. + +package gbinary_test + +import ( + "testing" + + "github.com/gogf/gf/g/encoding/gbinary" + "github.com/gogf/gf/g/test/gtest" +) + +func Test_LeEncodeAndLeDecode(t *testing.T) { + for k, v := range testData { + ve := gbinary.LeEncode(v) + ve1 := gbinary.LeEncodeByLength(len(ve), v) + + //t.Logf("%s:%v, encoded:%v\n", k, v, ve) + switch v.(type) { + case int: + gtest.Assert(gbinary.LeDecodeToInt(ve), v) + gtest.Assert(gbinary.LeDecodeToInt(ve1), v) + case int8: + gtest.Assert(gbinary.LeDecodeToInt8(ve), v) + gtest.Assert(gbinary.LeDecodeToInt8(ve1), v) + case int16: + gtest.Assert(gbinary.LeDecodeToInt16(ve), v) + gtest.Assert(gbinary.LeDecodeToInt16(ve1), v) + case int32: + gtest.Assert(gbinary.LeDecodeToInt32(ve), v) + gtest.Assert(gbinary.LeDecodeToInt32(ve1), v) + case int64: + gtest.Assert(gbinary.LeDecodeToInt64(ve), v) + gtest.Assert(gbinary.LeDecodeToInt64(ve1), v) + case uint: + gtest.Assert(gbinary.LeDecodeToUint(ve), v) + gtest.Assert(gbinary.LeDecodeToUint(ve1), v) + case uint8: + gtest.Assert(gbinary.LeDecodeToUint8(ve), v) + gtest.Assert(gbinary.LeDecodeToUint8(ve1), v) + case uint16: + gtest.Assert(gbinary.LeDecodeToUint16(ve1), v) + gtest.Assert(gbinary.LeDecodeToUint16(ve), v) + case uint32: + gtest.Assert(gbinary.LeDecodeToUint32(ve1), v) + gtest.Assert(gbinary.LeDecodeToUint32(ve), v) + case uint64: + gtest.Assert(gbinary.LeDecodeToUint64(ve), v) + gtest.Assert(gbinary.LeDecodeToUint64(ve1), v) + case bool: + gtest.Assert(gbinary.LeDecodeToBool(ve), v) + gtest.Assert(gbinary.LeDecodeToBool(ve1), v) + case string: + gtest.Assert(gbinary.LeDecodeToString(ve), v) + gtest.Assert(gbinary.LeDecodeToString(ve1), v) + case float32: + gtest.Assert(gbinary.LeDecodeToFloat32(ve), v) + gtest.Assert(gbinary.LeDecodeToFloat32(ve1), v) + case float64: + gtest.Assert(gbinary.LeDecodeToFloat64(ve), v) + gtest.Assert(gbinary.LeDecodeToFloat64(ve1), v) + default: + if v == nil { + continue + } + res := make([]byte, len(ve)) + err := gbinary.LeDecode(ve, res) + if err != nil { + t.Errorf("test data: %s, %v, error:%v", k, v, err) + } + gtest.Assert(res, v) + } + } +} + +func Test_LeEncodeStruct(t *testing.T) { + user := User{"wenzi1", 999, "www.baidu.com"} + ve := gbinary.LeEncode(user) + s := gbinary.LeDecodeToString(ve) + gtest.Assert(string(s), s) +} diff --git a/g/encoding/gbinary/gbinary_test.go b/g/encoding/gbinary/gbinary_z_test.go similarity index 96% rename from g/encoding/gbinary/gbinary_test.go rename to g/encoding/gbinary/gbinary_z_test.go index 7e875a9b4..1a6fc2c0c 100644 --- a/g/encoding/gbinary/gbinary_test.go +++ b/g/encoding/gbinary/gbinary_z_test.go @@ -7,12 +7,19 @@ package gbinary_test import ( - "github.com/gogf/gf/g/encoding/gbinary" - "github.com/gogf/gf/g/test/gtest" "math" "testing" + + "github.com/gogf/gf/g/encoding/gbinary" + "github.com/gogf/gf/g/test/gtest" ) +type User struct { + Name string + Age int + Url string +} + var testData = map[string]interface{}{ //"nil": nil, "int": int(123), @@ -39,7 +46,9 @@ var testData = map[string]interface{}{ "float64": float64(123.456), } -func TestEncodeAndDecode(t *testing.T) { +var testBitData = []int{0, 99, 122, 129, 222, 999, 22322} + +func Test_EncodeAndDecode(t *testing.T) { for k, v := range testData { ve := gbinary.Encode(v) ve1 := gbinary.EncodeByLength(len(ve), v) @@ -102,22 +111,14 @@ func TestEncodeAndDecode(t *testing.T) { } } -type User struct { - Name string - Age int - Url string -} - -func TestEncodeStruct(t *testing.T) { +func Test_EncodeStruct(t *testing.T) { user := User{"wenzi1", 999, "www.baidu.com"} ve := gbinary.Encode(user) s := gbinary.DecodeToString(ve) gtest.Assert(string(s), s) } -var testBitData = []int{0, 99, 122, 129, 222, 999, 22322} - -func TestBits(t *testing.T) { +func Test_Bits(t *testing.T) { for i := range testBitData { bits := make([]gbinary.Bit, 0) res := gbinary.EncodeBits(bits, testBitData[i], 64) diff --git a/geg/database/gdb/mssql/config.toml b/geg/database/gdb/mssql/config.toml index 8e44ef003..596f743f8 100644 --- a/geg/database/gdb/mssql/config.toml +++ b/geg/database/gdb/mssql/config.toml @@ -1,7 +1,7 @@ [database] type = "mssql" - host = "116.255.140.92" + host = "127.0.0.1" port = "1451" user = "sa" pass = "eno@123" diff --git a/geg/database/gdb/mssql/gdb_all.go b/geg/database/gdb/mssql/gdb_all.go index ad4c5806d..71d37a7c7 100644 --- a/geg/database/gdb/mssql/gdb_all.go +++ b/geg/database/gdb/mssql/gdb_all.go @@ -3,12 +3,12 @@ package main import ( "fmt" - //_ "github.com/denisenkom/go-mssqldb" + _ "github.com/denisenkom/go-mssqldb" "github.com/gogf/gf/g" ) func main() { - r, err := g.DB().GetAll(`SELECT * FROM (SELECT TOP 10 * FROM (SELECT TOP 10 * FROM KF_PatInfo_Emergency WHERE Report_BZ = 1 AND Examine_BZ = 0 ) as TMP1_ ) as TMP2_`) + r, err := g.DB().GetAll(`SELECT TOP 10 * FROM KF_PatInfo_Emergency`) fmt.Println(err) g.Dump(r.ToList()) } diff --git a/geg/database/gdb/mysql/gdb_all.go b/geg/database/gdb/mysql/gdb_all.go new file mode 100644 index 000000000..83e69972d --- /dev/null +++ b/geg/database/gdb/mysql/gdb_all.go @@ -0,0 +1,21 @@ +package main + +import ( + "fmt" + + "github.com/gogf/gf/g" +) + +func main() { + db := g.DB() + // 开启调试模式,以便于记录所有执行的SQL + db.SetDebug(true) + + r, e := db.Table("test").OrderBy("id asc").All() + if e != nil { + panic(e) + } + if r != nil { + fmt.Println(r.ToList()) + } +} diff --git a/geg/other/test.go b/geg/other/test.go index 9b345d623..f67617e91 100644 --- a/geg/other/test.go +++ b/geg/other/test.go @@ -1,39 +1,20 @@ package main import ( - "github.com/gogf/gf/g" - "github.com/gogf/gf/g/util/gvalid" + "fmt" + "math" + + "github.com/gogf/gf/g/encoding/gbinary" ) -type User struct { - Uid int `v:"uid @integer|min:1"` - Name string `v:"name @required|length:6,30#请输入用户名称|用户名称长度非法"` - Pass1 string `v:"password1@required|password3"` - Pass2 string `v:"password2@required|password3|same:password1#||两次密码不一致,请重新输入"` -} - func main() { - user := &User{ - Name: "john", - Pass1: "Abc123!@#", - Pass2: "123", - } + v := math.MaxUint16 + //v := []byte{255, 127} + //ve := gbinary.Encode(v) + //ve1 := gbinary.BeEncodeByLength(len(ve), v) + //fmt.Println(ve) + //fmt.Println(ve1) - // 使用结构体定义的校验规则和错误提示进行校验 - if e := gvalid.CheckStruct(user, nil); e != nil { - g.Dump(e.Maps()) - } - - // 自定义校验规则和错误提示,对定义的特定校验规则和错误提示进行覆盖 - rules := map[string]string{ - "uid": "min:6", - } - msgs := map[string]interface{}{ - "password2": map[string]string{ - "password3": "名称不能为空", - }, - } - if e := gvalid.CheckStruct(user, rules, msgs); e != nil { - g.Dump(e.Maps()) - } + //fmt.Println(gbinary.LeDecodeToInt(gbinary.LeEncode(v))) + fmt.Println(gbinary.BeDecodeToInt(gbinary.BeEncode(v))) }