Можно ли читать сообщения len (ch) из канала ch? - PullRequest
0 голосов
/ 06 июня 2019

Я запускаю одну программу для обработки сообщений канала, связанных с каким-либо пользователем.После обработки сообщений состояние пользователя обновляется и сохраняется в базе данных программой.Во время выполнения запроса к базе данных на канал может быть отправлено несколько сообщений.Я хотел бы обработать их все перед отправкой еще одного запроса в базу данных.

В настоящее время я использую len(ch) для проверки количества сообщений в канале и читаю их в цикле for.

func (c *consumer) handleUser(userID string, ch chan Message) {
  user := c.db.LoadUser(userID)
  for {
    var msgs []Message
    for n := len(ch); n > 0; n-- {
      msgs = append(msgs, <-ch)
    }
    apply.Messages(user, msgs)
    c.db.SaveUser(user)
}

ch := make(chan Message, 100)
go c.handleUser("user-1", ch) 

Я искал в Интернете, если это какая-то распространеннаяшаблон, но я не смог найти аналогичные решения, и мне интересно, является ли мой подход действительным / идиоматическим для программ go.

1 Ответ

1 голос
/ 06 июня 2019

Ваше решение приведет к тому, что порожденная программа будет вращаться по каналу, пока не будет отправлено хотя бы одно сообщение.Другими словами, рутина никогда не блокируется вообще.

Здесь вы пытаетесь обработать несколько сообщений в одном пакете.Есть разные способы реализовать это.Но основной вопрос, на который нужно ответить: откуда вы знаете, что пакет сообщений завершен? Программа-отправитель может обладать этими знаниями и может упаковывать все сообщения в один фрагмент.С другой стороны, вы можете не знать, когда партия будет готова.В этих случаях вам нужно использовать тайм-аут, как в следующем примере.

func (c *consumer) handleUser(userID string, ch chan Message) {
    user := c.db.LoadUser(userID)
    for {
        var msgs []Message
        select {
        case msg := <-ch:
            //Append the message in the current batch slice
            msgs = append(msgs, msg)
        //Wait up to 5 seconds and then process the batch
        case <-time.After(time.Second * 5):
            //Timeout: process the batch of messages
            if len(msgs) > 0 {
                apply.Messages(user, msgs)
                c.db.SaveUser(user)
            }
        }
    }
}

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

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