Как всегда получить последнее значение из канала Голанга? - PullRequest
0 голосов
/ 14 декабря 2018

Я начинаю с Go и сейчас пишу простую программу, которая считывает данные с датчика и помещает их в канал, чтобы выполнить с ним некоторые вычисления.Теперь у меня это работает следующим образом:

package main

import (
    "fmt"
    "time"
    "strconv"
)

func get_sensor_data(c chan float64) {
    time.Sleep(1 * time.Second)  // wait a second before sensor data starts pooring in
    c <- 2.1  // Sensor data starts being generated
    c <- 2.2
    c <- 2.3
    c <- 2.4
    c <- 2.5
}

func main() {

    s := 1.1

    c := make(chan float64)
    go get_sensor_data(c)

    for {
        select {
        case s = <-c:
            fmt.Println("the next value of s from the channel: " + strconv.FormatFloat(s, 'f', 1, 64))
        default:
            // no new values in the channel
        }
        fmt.Println(s)

        time.Sleep(500 * time.Millisecond)  // Do heavy "work"
    }
}

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

Есть ли способчтобы канал всегда содержал только одно значение за раз, чтобы я всегда получал только те данные, которые мне интересны, и канал не использует ненужную память (хотя эта память меньше всего беспокоит меня)?

Все советы приветствуются!

Ответы [ 3 ]

0 голосов
/ 14 декабря 2018

Каналы лучше всего рассматривать как очереди (FIFO).Поэтому вы не можете пропустить.Однако есть библиотеки, которые делают такие вещи: https://github.com/cloudfoundry/go-diodes - это атомарный кольцевой буфер, который будет перезаписывать старые данные.Вы можете установить меньший размер, если хотите.

Все это, как говорится, не похоже на то, что вам нужна очередь (или кольцевой буфер).Вам просто нужен мьютекс:

type SensorData struct{
  mu sync.RWMutex
  last float64
}

func (d *SensorData) Store(data float64) {
 mu.Lock()
 defer mu.Unlock()

 d.last = data
}

func (d *SensorData) Get() float64 {
 mu.RLock()
 defer mu.RUnlock()

 return d.last
}

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

0 голосов
/ 14 декабря 2018

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

Таким образом, получатель всегда получит последнее значение.

0 голосов
/ 14 декабря 2018

Нет.Каналы - это буферы FIFO, полная остановка.Так работают каналы и их единственная цель.Если вам нужно только последнее значение, попробуйте использовать только одну переменную, защищенную мьютексом;Пишите в нее всякий раз, когда поступают новые данные, и всякий раз, когда вы читаете их, вы всегда будете читать последнее значение.

...