I'm relatively new to Go, which is why I decided to post some code here. My goal is to en-/decode a TCP stream. The individual data packets length-based. The first two bytes are the unsigned size in little-endian byte order. The size includes the size field itself. The methods I wrote seem to en-/decode the packets as expected.
Is there a more efficient way to achieve this? Does Go perhaps already implement such methods somewhere.
func GetPacketByLength(source io.Reader) ([]byte, error) {
s := make([]byte, 2)
if _, err := io.ReadFull(source, s); err != nil {
return nil, err
}
// Little-endian uint16
size := uint16(s[0]) | uint16(s[1])<<8 - 2
p := make([]byte, size)
if _, err := io.ReadFull(source, p); err != nil {
return nil, err
}
return p, nil
}
func PutPacketByLength(target io.Writer, p []byte) error {
s := make([]byte, 2)
// Little-endian uint16
s[0] = byte((len(p) + 2))
s[1] = byte((len(p) + 2) >> 8)
if _, err := target.Write(s); err != nil {
return err
}
if _, err := target.Write(p); err != nil {
return err
}
return nil
}
1 Answer 1
You may consider to use binary.Read
. I find this more readable and self documented. See this example.
var len uint16
err := binary.Read(buf, binary.LittleEndian, &len)
The writing part:
len := uint16(len(p))
err := binary.Write(buf, binary.LittleEndian, len)
Also don't forget to check that len(p)
doesn't overflow uint16 (less than 65535).
Apart from that your code is fine.