func ParseDatagram(b []byte) (da Datagram, err error) {
	if len(b) < 4+net.IPv4len+2 {  
		err = errors.New("datagram to short")
		return
	}
	da.RSV, da.Frag, da.DstAddr.AddrType = 0, b[2], b[3]
	headLen := 4
	switch da.DstAddr.AddrType {
	case ATYPIPv4:
		headLen += net.IPv4len + 2
		da.DstAddr.IP = net.IPv4(b[4], b[5], b[6], b[7])
		da.DstAddr.Port = int(binary.BigEndian.Uint16((b[headLen-2:])))
	case ATYPIPv6:
		headLen += net.IPv6len + 2
		if len(b) <= headLen {
			err = errors.New("datagram to short")
			return
		}
		da.DstAddr.IP = b[4 : 4+net.IPv6len]
		da.DstAddr.Port = int(binary.BigEndian.Uint16(b[headLen-2:]))
	case ATYPDomain:
		addrLen := int(b[4])
		headLen += 1 + addrLen + 2
		if len(b) <= headLen {
			err = errors.New("datagram to short")
			return
		}
		da.DstAddr.FQDN = string(b[5 : 5+addrLen])
		da.DstAddr.Port = int(binary.BigEndian.Uint16(b[5+addrLen:]))
	default:
		err = ErrUnrecognizedAddrType
		return
	}
	da.Data = b[headLen:]
	return da, nil
}
ParseDatagram parse to datagram from bytes
package statute
import (
	"encoding/binary"
	"errors"
	"fmt"
	"math"
	"net"
)
type Datagram struct {
	RSV     uint16
	Frag    byte
	DstAddr AddrSpec
	Data    []byte
}
func NewDatagram(destAddr string, data []byte) (p Datagram, err error) {
	p.DstAddr, err = ParseAddrSpec(destAddr)
	if err != nil {
		return
	}
	if p.DstAddr.AddrType == ATYPDomain && len(p.DstAddr.FQDN) > math.MaxUint8 {
		err = errors.New("destination host name too long")
		return
	}
	p.RSV, p.Frag, p.Data = 0, 0, data
	return
}