Golang скрывает детали реализации канала

В моем коде у меня есть интерфейс

import amqp "github.com/rabbitmq/amqp091-go"

type Consumer interface {
    StartConsuming(queueName, key string) (<-chan amqp.Delivery, error)
}

с его внедрением

package rabbitmq

import amqp "github.com/rabbitmq/amqp091-go"

type Consumer struct {
    *Connection
}

func (c Consumer) StartConsuming(queueName, key string) (<-chan amqp.Delivery, error) {
    _, err := c.Channel.QueueDeclare(
        queueName,
        true,
        false,
        false,
        false,
        nil,
    )

    ...

    return c.Connection.Consume(
        queueName,
        "",
        false,
        false,
        false,
        false,
        nil,
    )
}

Дело в том, что в моем интерфейсе я не хочу указывать, что это доставка типа amqp.Delivery, я хочу, чтобы это было общее сообщение, чтобы я мог в любое время переключиться на любого другого брокера, например. MQTT. Но я не знаю, как вы можете сделать это более абстрактным и менее привязанным к реализации, чтобы его можно было оставить «немым». Обычно это было бы довольно просто со структурными переменными и т. д., но здесь этот канал мне еще немного неизвестен.

Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
Создание API ввода вопросов на разных языках программирования (Python, PHP, Go и Node.js)
API ввода вопросов - это полезный инструмент для интеграции моделей машинного обучения, таких как ChatGPT, в приложения, требующие обработки...
1
0
62
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Чтобы сделать интерфейс Consumer более абстрактным и менее привязанным к реализации, вы можете ввести новый тип сообщения, не зависящий от конкретной реализации брокера. Вот пример того, как вы можете этого добиться:

type Message interface {
    // Define the methods that your message type should have
    // to work with your application logic.
    // ...
}

type Consumer interface {
    StartConsuming(queueName, key string) (<-chan Message, error)
}

Создавая интерфейс Message, вы можете определить методы, которые должен иметь ваш тип сообщения, чтобы работать с логикой вашего приложения. Это позволяет отделить ваш код от конкретной реализации брокера.

Затем вы можете обновить свою реализацию rabbitmq.Consumer, чтобы она работала с интерфейсом Message вместо amqp.Delivery:

package rabbitmq

type Consumer struct {
    *Connection
}

func (c Consumer) StartConsuming(queueName, key string) (<-chan Message, error) {
    _, err := c.Channel.QueueDeclare(
        queueName,
        true,
        false,
        false,
        false,
        nil,
    )

    ...

    // Convert amqp.Delivery to your custom Message type
    convertToMessage := func(delivery amqp.Delivery) Message {
        // Implement the conversion logic from amqp.Delivery to your custom Message type.
        // ...
    }

    // Get the amqp.Delivery channel
    amqpDelivery, err := c.Connection.Consume(
        queueName,
        "",
        false,
        false,
        false,
        false,
        nil,
    )
    if err != nil {
        return nil, err
    }

    // Create a channel for your custom Message type
    messageChannel := make(chan Message)

    // Start a goroutine to convert amqp.Delivery to your custom Message type
    go func() {
        defer close(messageChannel)
        for delivery := range amqpDelivery {
            message := convertToMessage(delivery)
            messageChannel <- message
        }
    }()

    return messageChannel, nil
}

В приведенном выше коде функция convertToMessage преобразует amqp.Delivery в ваш пользовательский тип Message. Вам нужно будет реализовать эту логику преобразования в зависимости от потребностей вашего приложения.

Используя этот подход, вы можете сохранить свой интерфейс Consumer абстрактным и независимым от конкретной реализации брокера. Вы можете переключиться на другого брокера, например MQTT, предоставив другую реализацию интерфейса Consumer, которая работает с соответствующим типом сообщения для MQTT.

Примечание. Обязательно обновите другие части кода, использующие интерфейс Consumer, чтобы они также работали с типом Message.

Спасибо за ответ, в конечном итоге все сводится к «перелопачиванию» данных с одного канала на другой. Я не был слишком уверен, является ли это хорошей или плохой практикой, но я еще не знаю, что делать, поэтому я не могу точно сказать. Это обычная практика?

BrianM 03.06.2023 00:09

Да, это обычная практика в Go «перелопачивать» или перекидывать данные с одного канала на другой. Это шаблон, часто используемый для преобразования или адаптации данных между различными каналами или абстракциями. Такой подход позволяет отделить производителей и потребителей, обеспечивая большую гибкость и модульность кода. Хотя это может показаться дополнительным шагом, он обеспечивает четкое разделение задач и упрощает переключение или расширение реализации в будущем.

snwfdhmp 03.06.2023 00:11

Спасибо за объяснение, принял ваш ответ!

BrianM 03.06.2023 00:22

Вероятно, это было написано (полностью или частично) искусственным интеллектом (например, ChatGPT). Вы также опубликовали 6 других подробных ответов за последний час, которые, похоже, также были сгенерированы ИИ. Если вы использовали инструмент ИИ, чтобы помочь с каким-либо ответом, я бы посоветовал вам удалить его, так как публикация контента, созданного ИИ, здесь запрещена.

NotTheDr01ds 03.06.2023 01:24

Даже ваш комментарий, похоже, сгенерирован искусственным интеллектом!

NotTheDr01ds 03.06.2023 01:24

Читатели должны тщательно и критически рассмотреть этот ответ, поскольку информация, сгенерированная ИИ, часто содержит фундаментальные ошибки и дезинформацию. Если вы наблюдаете проблемы с качеством и/или у вас есть основания полагать, что этот ответ был сгенерирован искусственным интеллектом, пожалуйста, оставьте соответствующий отзыв. Команда модераторов может использовать вашу помощь для выявления проблем с качеством.

NotTheDr01ds 03.06.2023 01:25

Но является ли ответ по-прежнему действительным или нет?

BrianM 03.06.2023 10:37

@BrianM, я не вижу ничего действительно неправильного, но здесь вообще очень мало сути. Можно много говорить о том, что вы можете использовать интерфейс и (который даже не определен полезным образом) для содержания нескольких разных типов.

JimB 03.06.2023 19:10

Другие вопросы по теме