func ReadSingleEvent(conn *EventStoreConnection, streamID string, eventNumber int32, resolveLinkTos bool, requireMaster bool) (protobuf.ReadEventCompleted, error) {
	readEventsData := &protobuf.ReadEvent{
		EventStreamId:  proto.String(streamID),
		EventNumber:    proto.Int32(eventNumber),
		ResolveLinkTos: proto.Bool(resolveLinkTos),
		RequireMaster:  proto.Bool(requireMaster),
	}
	data, err := proto.Marshal(readEventsData)
	if err != nil {
		log.Fatal("marshaling error: ", err)
	}
	pkg, err := newPackage(readEvent, data, newPackageCorrelationID().Bytes(), conn.Config.Login, conn.Config.Password)
	if err != nil {
		log.Printf("[error] failed to create new read event package")
	}
	resultPackage, err := performOperation(conn, pkg, readEventCompleted)
	if err != nil {
		return protobuf.ReadEventCompleted{}, err
	}
	message := &protobuf.ReadEventCompleted{}
	proto.Unmarshal(resultPackage.Data, message)
	if *message.Result == protobuf.ReadEventCompleted_AccessDenied ||
		*message.Result == protobuf.ReadEventCompleted_Error {
		return *message, errors.New(message.Result.String())
	}
	if *message.Result == protobuf.ReadEventCompleted_Success {
		message.Event.Event.EventId = DecodeNetUUID(message.Event.Event.EventId)
	}
	return *message, nil
}
ReadSingleEvent reads a single event from a stream
package goes
import (
	"errors"
	"log"
	uuid "github.com/gofrs/uuid"
	"github.com/golang/protobuf/proto"
	"github.com/pgermishuys/goes/protobuf"
)
func marshalToProtobufEvents(evnts []Event) []*protobuf.NewEvent {
	var events []*protobuf.NewEvent
	for _, evnt := range evnts {
		dataContentType := int32(0)
		if evnt.IsJSON == true {
			dataContentType = 1
		}
		events = append(events,
			&protobuf.NewEvent{
				EventId:             EncodeNetUUID(evnt.EventID.Bytes()),
				EventType:           proto.String(evnt.EventType),
				DataContentType:     proto.Int32(dataContentType),
				MetadataContentType: proto.Int32(0),
				Data:                evnt.Data,
				Metadata:            evnt.Metadata,
			},
		)
	}
	return events
}
func performOperation(conn *EventStoreConnection, pkg TCPPackage, expectedResult Command) (TCPPackage, error) {
	resultChan := make(chan TCPPackage)
	sendPackage(pkg, conn, resultChan)
	result := <-resultChan
	if result.Command != expectedResult {
		return result, errors.New(result.Command.String())
	}
	return result, nil
}
func shouldRetryOperation(operationResult *protobuf.OperationResult) (bool, error) {
	if *operationResult == protobuf.OperationResult_AccessDenied ||
		*operationResult == protobuf.OperationResult_WrongExpectedVersion {
		return false, errors.New(operationResult.String())
	}
	if *operationResult == protobuf.OperationResult_CommitTimeout ||
		*operationResult == protobuf.OperationResult_PrepareTimeout ||
		*operationResult == protobuf.OperationResult_ForwardTimeout {
		return true, nil
	}
	return false, nil
}
func newPackageCorrelationID() uuid.UUID {
	corrID, err := uuid.NewV4()
	if err != nil {
		log.Fatalf("[fatal] failed to create new correlationID for package: %+v\n", err)
	}
	return corrID
}
func AppendToStream(conn *EventStoreConnection, streamID string, expectedVersion int32, evnts []Event) (protobuf.WriteEventsCompleted, error) {
	events := marshalToProtobufEvents(evnts)
	writeEventsData := &protobuf.WriteEvents{
		EventStreamId:   proto.String(streamID),
		ExpectedVersion: proto.Int32(expectedVersion),
		Events:          events,
		RequireMaster:   proto.Bool(true),
	}
	data, err := proto.Marshal(writeEventsData)
	if err != nil {
		log.Printf("[error] marshaling error: %s", err)
		return protobuf.WriteEventsCompleted{}, err
	}
	pkg, err := newPackage(writeEvents, data, newPackageCorrelationID().Bytes(), conn.Config.Login, conn.Config.Password)
	if err != nil {
		log.Printf("[error] failed to create new write events package")
		return protobuf.WriteEventsCompleted{}, err
	}
	for i := 0; i < conn.Config.MaxOperationRetries; i++ {
		resultPackage, err := performOperation(conn, pkg, writeEventsCompleted)
		if err != nil {
			return protobuf.WriteEventsCompleted{}, err
		}
		message := &protobuf.WriteEventsCompleted{}
		proto.Unmarshal(resultPackage.Data, message)
		shouldRetry, err := shouldRetryOperation(message.Result)
		if err != nil || !shouldRetry {
			return *message, err
		}
	}
	return protobuf.WriteEventsCompleted{}, errors.New("Retry limit reached")
}