Мой сценарий:
- У меня есть производитель и потребитель.Оба являются goroutines, и они общаются через один канал.
- Производитель способен (теоретически) генерировать сообщение в любое время.
- Генерация сообщения требует некоторых вычислений.
- Сообщение несколько чувствительно ко времени (т. Е. Чем оно старше, тем оно менее актуально).
- Пользователь время от времени читает с канала.В качестве примера, скажем, потребитель использует
time.Ticker
для чтения сообщения раз в пару секунд. - Потребитель предпочел бы «свежие» сообщения (т.е. сообщения, которые были сгенерированы как можно раньше).).
Итак, вопрос в следующем: Как производитель может сгенерировать сообщение как можно позже?
Пример кода, который показывает общиеидея:
func producer() {
for {
select {
...
case pipe <- generateMsg():
// I'd like to call generateMsg as late as possible,
// i.e. calculate the timestamp when I know
// that writing to the channel will not block.
}
}
}
func consumer() {
for {
select {
...
case <-timeTicker.C:
// Reading from the consumer.
msg <- pipe
...
}
}
}
Полный код (немного отличающийся от приведенного выше) доступен на игровой площадке Go: https://play.golang.org/p/y0oCf39AV6P
Одна из идей, которую у меня возникла, заключалась в проверке записи в канал.будет блокировать.Если он не заблокируется, я могу сгенерировать сообщение и затем отправить его.Однако…
- Я не смог найти способа проверить, будет ли запись в канал заблокирована или нет.
- В общем случае это плохая идея, потому что она вводитгоночные условия, если у нас несколько производителей.В этом конкретном случае у меня есть только один производитель.
Еще одна (плохая) идея:
func producer() {
var msg Message
for {
// This is BAD. DON'T DO THIS!
select {
case pipe <- msg:
// It may send the same message multiple times.
default:
msg = generateMsg()
// It causes a busy-wait loop, high CPU usage
// because it re-generates the message all the time.
}
}
}