Golang Go语言中用golang写了一个字节数据的编解码, 可以简化编写TCP服务时, 消息的封装和解析
Golang Go语言中用golang写了一个字节数据的编解码, 可以简化编写TCP服务时, 消息的封装和解析
https://github.com/lai323/bytecodec
这个库实现 []byte
到 struct
编解码, 对于要处理特别多结构不同的字节消息
使用这个就不用每种消息类型都去写编解码了
可以向处理 json 一样处理字节数据
package main
import (
“fmt”
“time”
"github.com/lai323/bytecodec"
)
type Header struct {
SerialNo uint16
Time int64
}
type Packet struct {
Header Header
Phone string bytecodec:"length:11"
// 使用长度固定为 11 的字符串
MsgLength uint8 bytecodec:"lengthref:Msg"
// 表示这个字段的值是 Msg 的字节长度
Msg string bytecodec:"gbk"
// 使用 GBK 编码
}
func main() {
p := Packet{
Header: Header{
SerialNo: 1,
Time: time.Now().Unix(),
},
Phone: “18102169375”,
Msg: “你好”,
}
b, err := bytecodec.Marshal(p)
fmt.Println(fmt.Sprintf("%#v", b), err)
out := &Packet{}
err = bytecodec.Unmarshal(b, out)
fmt.Println(fmt.Sprintf("%#v", out), err)
}
更多关于Golang Go语言中用golang写了一个字节数据的编解码, 可以简化编写TCP服务时, 消息的封装和解析的实战教程也可以访问 https://www.itying.com/category-94-b0.html
关于序列化,protobuf/json 足够用了,并且还有其他一大堆知名的序列化方案可选。
另外,是否支持完备的嵌套,比如是否支持 struct 内的 struct 成员、数组成员、数组成员的元素是 struct 等。如果支持,算是相对完善,剩下的要看性能,如果不支持,对业务太不友好了。对于性能,主要是两个方面考量,一是速度,二是生成的数据长度。因为是用注释的方式,也就意味着要反射,性能可能不会比 protobuf 这些生成代码的快、长度也不会比 protobuf 能省,因为没有按照固定的 proto 生成固定的代码,所以传输给对方解码时仍需要带上 key 信息,相比 json 倒是可以把一些引号冒号省了,但可能又跟 MessagePack 差不多了。
单就序列化,对简化 tcp 服务消息封装和解析帮助不大。楼主应该是指这个 Header 做包长相关的流到包的解析。这个对于 go 也比较简单,单独协程读的方案,有 ReadFull 这些方便的方法,不需要像 c/c++ 那些异步解析稍微费神(但是异步解析费神也不算太多)。所以,整体看,tcp 服务也没必要用这种序列化方案。实现这种序列化,对学习和提高编解码能力是好事情,但建议使用更成熟优秀的方案。
更多关于Golang Go语言中用golang写了一个字节数据的编解码, 可以简化编写TCP服务时, 消息的封装和解析的实战系列教程也可以访问 https://www.itying.com/category-94-b0.html
感谢指教,这个库的目的不是要发明一种速度快、体积小序列化方式,主要是处理字节流到对象具体属性的映射,比如车载终端或 POS 机里面一些基于 TCP 通信标准,这些标准会定义比较多的消息类型,每种消息结构不一样,我需要针对不同消息写一个编解码,这里面有非常多的重复工作,例如:读取一个 byte,读取一个固定长度的字符串,先读一个长度,再按长度读一个字节数组,这个库是为了处理这些重复工作
这个库支持对象的嵌套,因为要解析未知 struct 使用了反射,tag 只是做一下辅助,数据转换主要还是看字段数据类型
gob,pb 不香么?
我在上家公司为了对接之前的老项目,也写过类似的代码. 应该还是有应用场景的.
很多人没用过二进制协议所以不是很清楚吧,你这个 benchmark 做了没
很棒的工具
只做了功能性测试,性能方面只对 struct 的字段做了一下缓存,不至于每次都解析 stuct,性能应该不会太好,估计和 json 标准库差不多
从例子中看,使用起来挺简单的。
感觉这个库是个对二进制数据封包和拆包的 helper 。如果是个 packer 的话,第一感觉是应当实现 pack() / unpack() 方法,而不是 marshal / unmarshal, 后者更像是对数据的编码,属于 codec,例如 json / protobuf 。
封包拆包可以看下这两个库 https://github.com/smallnest/goframe 和 https://github.com/zhuangsirui/binpacker 。
在Go语言中,编写字节数据的编解码器对于简化TCP服务的消息封装和解析确实是一个非常实用的技能。以下是一些关键点,可以帮助你优化和确保你的编解码器的可靠性和高效性:
-
协议设计:首先,设计一个清晰的协议,包括消息头部(如消息长度、类型、时间戳等)和数据部分的格式。这有助于在接收端正确解析消息。
-
序列化与反序列化:使用标准库中的
encoding/binary
、encoding/json
或encoding/xml
等包进行数据的序列化和反序列化。确保在编码和解码时使用相同的规则和格式。 -
错误处理:在解码过程中,增加错误处理逻辑,比如检查数据长度、校验和等,以确保数据的完整性和正确性。
-
性能优化:对于高并发场景,考虑使用缓冲区池(如
sync.Pool
)来减少内存分配和垃圾回收的开销。此外,使用高效的编码算法和数据结构也能提升性能。 -
测试:编写单元测试和集成测试,确保编解码器在各种情况下都能正确工作。特别是边界条件和异常情况下的测试。
-
文档:为协议和编解码器编写详细的文档,以便其他开发人员理解和维护代码。
通过上述步骤,你可以创建一个健壮、高效且易于维护的字节数据编解码器,从而简化TCP服务的消息封装和解析工作。如果有更具体的问题或需要进一步的帮助,请随时提问。