golang 仿python pack/unpack

wangxusummer · · 6894 次点击 · · 开始浏览    
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

写得不完善也不完美 尤其是高低位转换那(go和c 二进制高地位相反 需要转换,还有go int转[]byte长度是4位),希望牛人看后指导一下

项目需要通过socket调取 客户端是go ,服务器端是python,由于需要封包解包,就参照python写的

python 的pack/unpack 参考  Python使用struct处理二进制(pack和unpack用法)

package includes

import (
    "bytes"
    "encoding/binary"
    "fmt"
    _ "os"
    "strconv"
    "strings"
)

type Protocol struct {
    Format []string
}

//封包
func (p *Protocol) Pack(args ...interface{}) []byte {
    la := len(args)
    ls := len(p.Format)
    ret := []byte{}
    if ls > 0 && la > 0 && ls == la {
        for i := 0; i < ls; i++ {
            if p.Format[i] == "H" {
                ret = append(ret, IntToBytes2(args[i].(int))...)
            } else if p.Format[i] == "I" {
                ret = append(ret, IntToBytes4(args[i].(int))...)
            } else if strings.Contains(p.Format[i], "s") {
                num, _ := strconv.Atoi(strings.TrimRight(p.Format[i], "s"))
                ret = append(ret, []byte(fmt.Sprintf("%s%s", args[i].(string), strings.Repeat("\x00", num-len(args[i].(string)))))...)
            }
        }
    }
    return ret
}

//解包
func (p *Protocol) UnPack(msg []byte) []interface{} {
    la := len(p.Format)
    ret := make([]interface{}, la)
    if la > 0 {
        for i := 0; i < la; i++ {
            if p.Format[i] == "H" {
                ret[i] = Bytes4ToInt(msg[0:2])
                msg = msg[2:len(msg)]
            } else if p.Format[i] == "I" {
                ret[i] = Bytes4ToInt(msg[0:4])
                msg = msg[4:len(msg)]
            } else if strings.Contains(p.Format[i], "s") {
                num, _ := strconv.Atoi(strings.TrimRight(p.Format[i], "s"))
                ret[i] = string(msg[0:num])
                msg = msg[num:len(msg)]

            }
        }
    }
    return ret
}

func (p *Protocol) Size() int {
    size := 0
    ls := len(p.Format)
    if ls > 0 {
        for i := 0; i < ls; i++ {
            if p.Format[i] == "H" {
                size = size + 2
            } else if p.Format[i] == "I" {
                size = size + 4
            } else if strings.Contains(p.Format[i], "s") {
                num, _ := strconv.Atoi(strings.TrimRight(p.Format[i], "s"))
                size = size + num
            }
        }
    }
    return size
}

//整形转换成字节
func IntToBytes(n int) []byte {
    m := int32(n)
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, m)

    gbyte := bytesBuffer.Bytes()

    return gbyte
}

//整形转换成字节4位
func IntToBytes4(n int) []byte {
    m := int32(n)
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, m)

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

//整形转换成字节2位
func IntToBytes2(n int) []byte {
    m := int32(n)
    bytesBuffer := bytes.NewBuffer([]byte{})
    binary.Write(bytesBuffer, binary.BigEndian, m)

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

//字节转换成整形
func BytesToInt(b []byte) int {
    bytesBuffer := bytes.NewBuffer(b)

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

    return int(x)
}

//4个字节转换成整形
func Bytes4ToInt(b []byte) int {
    xx := make([]byte, 4)
    if len(b) == 2 {
        xx = []byte{b[0], b[1], 0, 0}
    } else {
        xx = b
    }

    m := len(xx)
    nb := make([]byte, 4)
    for i := 0; i < 4; i++ {
        nb[i] = xx[m-i-1]
    }
    bytesBuffer := bytes.NewBuffer(nb)

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

    return int(x)
}

 

调用

p := new(Protocol)
p.Format = []string{"H", "H", "I", "16s", "I", "I", "I"}
h_byte := p.Pack(1, 1, 1, "abc", 1, 0, len(request_buf))
conn.Write(h_byte)

 

附加:

int 转 二进制 fmt.Printf("%08b\n", 97) // 01100001

二进制转int i, _ := strconv.ParseInt("1100001", 2, 32) //97

int 转 []byte IntToBytes(1000) // [0 0 3 232]  3*256+232=1000

func IntToBytes(n int) []byte {
m := int32(n)
bytesBuffer := bytes.NewBuffer([]byte{})
binary.Write(bytesBuffer, binary.BigEndian, m)

gbyte := bytesBuffer.Bytes()

return gbyte
}

[]byte 转int BytesToInt([]byte{0,0,3,232}) //1000

func BytesToInt(b []byte) int {
bytesBuffer := bytes.NewBuffer(b)

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

return int(x)
}

intbyte byte(97) //97

 

本文来自:博客园

感谢作者:wangxusummer

查看原文:golang 仿python pack/unpack

入群交流(和以上内容无关):加入Go大咖交流群,免费领全套学习资料或添加微信:muxilin131420 备注:入群;或加QQ群:729884609

6894 次点击  
加入收藏 微博
1 回复  |  直到 2000-01-01 00:00:00
暂无回复
添加一条新回复 (您需要 登录 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传