frame.go
func ReadFrame(r *bufio.Reader) (frame Frame, err error) {
	var size int32
	var ftype int32

	if err = binary.Read(r, binary.BigEndian, &size); err != nil {
		err = errors.Wrap(err, "reading frame size")
		return
	}

	if err = binary.Read(r, binary.BigEndian, &ftype); err != nil {
		err = errors.Wrap(err, "reading frame type")
		return
	}

	switch size -= 4; FrameType(ftype) {
	case FrameTypeResponse:
		return readResponse(int(size), r)

	case FrameTypeError:
		return readError(int(size), r)

	case FrameTypeMessage:
		return readMessage(int(size), r)

	default:
		return readUnknownFrame(FrameType(ftype), int(size), r)
	}
}
func ReadFrame(r *bufio.Reader) (frame Frame, err error) {
	var size int32
	var ftype int32

	if err = binary.Read(r, binary.BigEndian, &size); err != nil {
		err = errors.Wrap(err, "reading frame size")
		return
	}

	if err = binary.Read(r, binary.BigEndian, &ftype); err != nil {
		err = errors.Wrap(err, "reading frame type")
		return
	}

	switch size -= 4; FrameType(ftype) {
	case FrameTypeResponse:
		return readResponse(int(size), r)

	case FrameTypeError:
		return readError(int(size), r)

	case FrameTypeMessage:
		return readMessage(int(size), r)

	default:
		return readUnknownFrame(FrameType(ftype), int(size), r)
	}
}
// ReadFrame reads a frame from the buffer input r, returning it or an error if
// something went wrong.
//
//	if frame, err := ReadFrame(r); err != nil {
//		// handle the error
//		...
//	} else {
//		switch f := frame.(type) {
//		case nsq.Message:
//			...
//		}
//	}
//