code: func (conn *ProtoConnectionFields) sendAsyncMessage(topic string, partition int32, key string, value proto.Message, manualMode bool,
  	meta interface{}, successClb func(messaging.ProtoMessage), errClb func(messaging.ProtoMessageErr)) error {
  	data, err := conn.serializer.Marshal(value)
  	if err != nil {
  		return err
  	}
  	succByteClb := func(msg *client.ProducerMessage) {
  		protoMsg := &client.ProtoProducerMessage{
  			ProducerMessage: msg,
  			Serializer:      conn.serializer,
  		}
  		successClb(protoMsg)
  	}
  
  	errByteClb := func(msg *client.ProducerError) {
  		protoMsg := &client.ProtoProducerMessageErr{
  			ProtoProducerMessage: &client.ProtoProducerMessage{
  				ProducerMessage: msg.ProducerMessage,
  				Serializer:      conn.serializer,
  			},
  			Err: msg.Err,
  		}
  		errClb(protoMsg)
  	}
  
  	if manualMode {
  		auxMeta := &asyncMeta{successClb: succByteClb, errorClb: errByteClb, usersMeta: meta}
  		conn.multiplexer.manAsyncProducer.SendMsgToPartition(topic, partition, sarama.StringEncoder(key), sarama.ByteEncoder(data), auxMeta)
  		return nil
  	}
  	auxMeta := &asyncMeta{successClb: succByteClb, errorClb: errByteClb, usersMeta: meta}
  	conn.multiplexer.hashAsyncProducer.SendMsgToPartition(topic, partition, sarama.StringEncoder(key), sarama.ByteEncoder(data), auxMeta)
  	return nil
  }
docs: // sendAsyncMessage sends a message using the async API. If manual mode is chosen, the appropriate producer will be used.