Лучший способ обрабатывать случаи в зависимости от типов в Go lang - PullRequest
0 голосов
/ 21 февраля 2019

Я новичок в Go lang, и я мог бы воспользоваться некоторыми советами о том, как изменить код.Все, что мне нужно сделать, это в зависимости от успеха или ошибки от Sarama (Apache Kafka в ходу), мне нужно войти и переслать дальше.Пока мой код выглядит таккак показано здесь

func checkSuccessOrFailAck(msg interface{}) {
    switch msgType := msg.(type) {
    case producer.Errors:
        batchID := msg.Msg.Metadata.(ackMeta).batchID
        statusChan := msg.Msg.Metadata.(ackMeta).statusChan
        statusChan <- false
        close(statusChan)
        logs.Debug(appName, "Signalled failure on statusChan for batch ", batchID)
        logs.Error(appName, "Failed to publish data to analyzer for batchID: ", batchID, msg)
    case producer.Successes:
        batchID := msg.Metadata.(ackMeta).batchID
        statusChan := msg.Metadata.(ackMeta).statusChan
        statusChan <- true
        close(statusChan)
        logs.Debug(appName, "Signalled success on statusChan for batch ", batchID)
        logs.Debug(appName, "Successfully  published data to analyzer:", succ.Topic, succ.Key, succ.Partition, succ.Offset, succ.Metadata)
    }

}

Типы сообщений различны, как и способ извлечения атрибутов из него.Но я не доволен этим подходом, так как заявления больше, чем предыдущий.Может ли быть лучший способ думать, чтобы написать?

Ответы [ 2 ]

0 голосов
/ 21 февраля 2019

Вы можете сделать их оба в одной процедуре, используя select:

go func() {
    errsOpen := true
    succsOpen := true
    for errsOpen && succsOpen {
        select {
        case err,errsOpen := <- producer.Errors()
            batchID := err.Msg.Metadata.(ackMeta).batchID # notice the struct here
            statusChan := err.Msg.Metadata.(ackMeta).statusChan
            statusChan <- false
            close(statusChan)
            logs.Debug(appName, "Signalled failure on statusChan for batch ", batchID)
            logs.Error(appName, "Failed to publish data to analyzer for batchID: ", batchID, err)

        case succ,succsOpen := <- producer.Successes()
            batchID := succ.Metadata.(ackMeta).batchID        # notice the struct here
            statusChan := succ.Metadata.(ackMeta).statusChan
            statusChan <- true
            close(statusChan)
            logs.Debug(appName, "Signalled success on statusChan for batch ", batchID)
            logs.Debug(appName, "Successfully  published data to analyzer:", succ.Topic, succ.Key, succ.Partition, succ.Offset, succ.Metadata)
        }
    }
}()

Это будет цикл до тех пор, пока оба канала не будут закрыты, и на каждой итерации цикла обрабатывает значение из любого канала, который имеетзначение, ожидающее получения (или, если оба значения ожидают, выберите случайное значение).

0 голосов
/ 21 февраля 2019

Во-первых, не ясно, работает ли второй код вообще.Поскольку Errors() и Successes() возвращают каналы, вам нужно select, чтобы считывать оба из них одновременно без блокировки.

Поскольку succ и err имеют разные типы в кодеЯ не уверен, что вы можете сделать это намного короче, чем ваш оригинальный образец.У Go пока нет дженериков, поэтому написание кода, который бы объединил их, является сложной задачей.Если вам действительно это нужно, я постараюсь найти ближайшие точки, где тип одинаковый - с этого момента будет проще объединить код.например err.Msg и succ - это один и тот же тип?

Более того, даже если у Go уже есть дженерики, не ясно, объединит ли это, что это будет победой.Философия Go заключается в том, что небольшое повторение кода лучше, чем чрезмерно сложные абстракции.Код не самый короткий, каким он может быть в теории, но он явный и понятный.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...