GO 實現一個 PACK 和 UnPack

不忘初心發表於2019-07-21

PACK 實現(暫時:僅限於數字)

package pack

import (
    "bytes"
    "encoding/binary"
    "fmt"
    "log"
    "math"
    "strconv"
    "strings"
)

type Protocol struct {
    Format []string
}

//編碼
func (p *Protocol) Pack(args ...int64) (ret []byte) {
    la := len(args)
    ls := len(p.Format)

    if ls > 0 && la > 0 && ls == la {
        for i := 0; i < la; i++ {
            if p.Format[i] == "N8" {
                ret = append(ret, IntToBytes8(args[i])...)
            } else if p.Format[i] == "N4" {
                ret = append(ret, IntToBytes4(args[i])...)
            } else if p.Format[i] == "N2" {
                ret = append(ret, IntToBytes2(args[i])...)
            }

        }
    }

    return ret
}

//解碼
func (p *Protocol) UnPack(data []byte) []int64 {
    la := len(p.Format)
    ret := make([]int64, la)

    if la > 0 {
        for i := 0; i < la; i++ {
            if p.Format[i] == "N8" {
                ret[i] = Bytes8ToInt64(data[0:8])
                data = data[8:]
            } else if p.Format[i] == "N4" {
                ret[i] = Bytes4ToInt64(data[0:4])
                data = data[4:]
            } else if p.Format[i] == "N2" {
                ret[i] = Bytes2ToInt64(data[0:2])
                data = data[2:]
            }
        }
    }

    return ret
}

//轉成16進位制編碼字串
func (p *Protocol) Pack16(args ...int64) (hString string) {
    //變成 byte 碼
    hByte := p.Pack(args...)
    //轉成 16進位制字串
    hString = p.DecToHexString(hByte)

    return hString
}

//解碼16進位制字串
func (p *Protocol) UnPack16(hString string) (unIntList []int64) {
    HSByte := p.HexStringToByte(hString)
    unIntList = p.UnPack(HSByte)

    return unIntList
}

//10進位制轉16進位制字串
func (p *Protocol) DecToHexString(decString []byte) (responseStr string) {
    for _, v := range decString {
        hexString := DecHex(int64(v))

        if len(hexString) < 2 {
            hexString = "0" + hexString
        }

        responseStr += hexString
    }

    return strings.ToLower(responseStr)
}

//16進位制字串轉位元組型別
func (p *Protocol) HexStringToByte(hexString string) (responseByte []byte) {
    ls := len(hexString) / 2

    for i := 0; i < ls; i++ {
        hex := hexString[0:2]
        hexString = hexString[2:]
        responseByte = append(responseByte, IntToBytes1(HexDec(hex))...)
    }

    return
}

//int64 轉 byte8
func IntToBytes8(n int64) []byte {
    var buf = make([]byte, 8)
    binary.BigEndian.PutUint64(buf, uint64(n))
    return buf
}

//int64 轉 byte4
func IntToBytes4(n int64) []byte {
    nb := intToBytes(n, 4)
    return nb
}

//int64 轉 byte2
func IntToBytes2(n int64) []byte {
    nb := intToBytes(n, 2)
    return nb
}

//int64 轉 byte1
func IntToBytes1(n int64) []byte {
    nb := intToBytes(n, 1)
    return nb
}

//int64 轉 byteN
func intToBytes(n int64, k int) []byte {
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, n)

    gbyte := bytesBuffer.Bytes()
    //c++ 高低位轉換
    x := len(gbyte)
    nb := make([]byte, k)
    for i := 0; i < k; i++ {
        nb[i] = gbyte[x-i-1]
    }
    return nb
}

//byte2 轉 int64
func Bytes2ToInt64(b []byte) int64 {
    nb := []byte{0, 0, b[1], b[0]}

    bytesBuffer := bytes.NewBuffer(nb)

    var x int32
    binary.Read(bytesBuffer, binary.BigEndian, &x)

    return int64(x)
}

//byte4 轉 int64
func Bytes4ToInt64(b []byte) int64 {
    nb := []byte{b[3], b[2], b[1], b[0]}

    bytesBuffer := bytes.NewBuffer(nb)

    var x int32
    binary.Read(bytesBuffer, binary.BigEndian, &x)

    return int64(x)
}

//byte8 轉 int64
func Bytes8ToInt64(buf []byte) int64 {
    return int64(binary.BigEndian.Uint64(buf))
}

//10進位制 轉 16進位制
func DecHex(n int64) string {
    if n < 0 {
        log.Println("Decimal to hexadecimal error: the argument must be greater than zero.")
        return ""
    }
    if n == 0 {
        return "0"
    }
    hex := map[int64]int64{10: 65, 11: 66, 12: 67, 13: 68, 14: 69, 15: 70}
    s := ""
    for q := n; q > 0; q = q / 16 {
        m := q % 16
        if m > 9 && m < 16 {
            m = hex[m]
            s = fmt.Sprintf("%v%v", string(m), s)
            continue
        }
        s = fmt.Sprintf("%v%v", m, s)
    }
    return s
}

//16進位制 轉 10進位制
func HexDec(h string) (n int64) {
    s := strings.Split(strings.ToUpper(h), "")
    l := len(s)
    i := 0
    d := float64(0)
    hex := map[string]string{"A": "10", "B": "11", "C": "12", "D": "13", "E": "14", "F": "15"}
    for i = 0; i < l; i++ {
        c := s[i]
        if v, ok := hex[c]; ok {
            c = v
        }
        f, err := strconv.ParseFloat(c, 10)
        if err != nil {
            log.Println("Hexadecimal to decimal error:", err.Error())
            return -1
        }
        d += f * math.Pow(16, float64(l-i-1))
    }
    return int64(d)
}

使用測試:

package pack

import (
    "fmt"
    "testing"
)

func TestPack(t *testing.T) {
    p := new(Protocol)
    //這個例子 N8:4294967295  N4:2147483647  N2:65535
    p.Format = []string{"N8", "N2", "N4"}
    maxString := p.Pack16(4294967295, 65535, 2147483647)
    MaxUnInt64List := p.UnPack16(maxString)
    fmt.Println(maxString, "---", MaxUnInt64List)

    //這個例子 N8:-4294967295  N4:-2147483647  N2:0
    p.Format = []string{"N8", "N2", "N4"}
    MinString := p.Pack16(-4294967295, 0, -2147483647)
    MinUnInt64List := p.UnPack16(MinString)
    fmt.Println(MinString, "---", MinUnInt64List)
}

相關文章