Repository: apache/pulsar-client-go (go)
Issue: Make MessageID In my Project
**Is your feature request related to a problem? Please describe.**
Why not provide a public implementation about MessageID

**Describe the solution you'd like**
NewMessageID(ledgerID int64, entryID int64, batchIdx int, partitionIdx int)

**Describe alternatives you've considered**
I need Seek() from customized messageID

**Additional context**

I am developing a management platform，need to start consumption from the specified location.
So I hope I can create the message ID by myself
Pull request description: [Issue 453] Add NewMessageID() method.
Fixes #453 

### Motivation

Sometimes we need to deal with some messages manually.

```go
pb "github.com/apache/pulsar-client-go/pulsar/internal/pulsar_proto"

	msgID := &pb.MessageIdData{
		LedgerId:             proto.Uint64(699),
		EntryId:              proto.Uint64(11),
		Partition:            proto.Int32(0),
		BatchIndex:           proto.Int32(0),
	}
	bytes, _ := proto.Marshal(msgID)
	id, _ := pulsar.DeserializeMessageID(bytes)
	err = consumer.AckID(id)
```
Here is the nonsensical serialization and deserialization code, also `pb` is an internal package and cannot be accessed externally.


### Modifications

Add the `NewMessageID()` method.


### Verifying this change

- [x] Make sure that the change passes the CI checks.



Patch:
diff --git a/pulsar/message.go b/pulsar/message.go
index c117c99..7f2e07f 100644
--- a/pulsar/message.go
+++ b/pulsar/message.go
@@ -161,6 +161,11 @@ func DeserializeMessageID(data []byte) (MessageID, error) {
 	return deserializeMessageID(data)
 }
 
+// NewMessageID Custom Create MessageID
+func NewMessageID(ledgerID int64, entryID int64, batchIdx int32, partitionIdx int32) MessageID {
+	return newMessageID(ledgerID, entryID, batchIdx, partitionIdx)
+}
+
 // EarliestMessageID returns a messageID that points to the earliest message available in a topic
 func EarliestMessageID() MessageID {
 	return earliestMessageID


Test patch:
diff --git a/pulsar/consumer_test.go b/pulsar/consumer_test.go
index e9b3013..989b906 100644
--- a/pulsar/consumer_test.go
+++ b/pulsar/consumer_test.go
@@ -3303,3 +3303,46 @@ func TestConsumerWithBackoffPolicy(t *testing.T) {
 	partitionConsumerImp.reconnectToBroker()
 	assert.True(t, backoff.IsExpectedIntervalFrom(startTime))
 }
+
+func TestAckWithMessageID(t *testing.T) {
+	client, err := NewClient(ClientOptions{
+		URL: lookupURL,
+	})
+
+	assert.Nil(t, err)
+	defer client.Close()
+
+	topic := newTopicName()
+
+	// create consumer
+	consumer, err := client.Subscribe(ConsumerOptions{
+		Topic:            topic,
+		SubscriptionName: "my-sub",
+		Type:             Exclusive,
+	})
+	assert.Nil(t, err)
+	defer consumer.Close()
+
+	// create producer
+	producer, err := client.CreateProducer(ProducerOptions{
+		Topic:           topic,
+		DisableBatching: false,
+	})
+	assert.Nil(t, err)
+	defer producer.Close()
+
+	// send messages
+	if _, err := producer.Send(context.Background(), &ProducerMessage{
+		Payload: []byte("hello"),
+	}); err != nil {
+		log.Fatal(err)
+	}
+
+	message, err := consumer.Receive(context.Background())
+	assert.Nil(t, err)
+
+	id := message.ID()
+	newID := NewMessageID(id.LedgerID(), id.EntryID(), id.BatchIdx(), id.PartitionIdx())
+	err = consumer.AckID(newID)
+	assert.Nil(t, err)
+}