doumin4553
2018-12-13 22:05
浏览 38
已采纳

如何始终从golang渠道获取最新价值?

I'm starting out with Go and I'm now writing a simple program which reads out data from a sensor and puts that into a channel to do some calculations with it. I now have it working as follows:

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"
    }
}

This works fine, but the sensor generates a lot of data, and I'm always only interested in the latest data. With this setup however, it only reads out the next item with every loop, which means that if the channel at some point contains 20 values, the newest value only is read out after 10 seconds.

Is there a way for a channel to always only contain one value at a time, so that I always only get the data I'm interested in, and no unnecessary memory is used by the channel (although the memory is the least of my worries)?

All tips are welcome!

  • 点赞
  • 写回答
  • 关注问题
  • 收藏
  • 邀请回答

3条回答 默认 最新

  • douhanzhen8927 2018-12-13 22:15
    已采纳

    Channels are best thought of as queues (FIFO). Therefore you can't really skip around. However there are libraries out there that do stuff like this: https://github.com/cloudfoundry/go-diodes is an atomic ring buffer that will overwrite old data. You can set a smaller size if you like.

    All that being said, it doesn't sound like you need a queue (or ring buffer). You just need a mutex:

    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
    }
    

    This uses a RWMutex which means many things can read from it at the same time while only a single thing can write. It will store a single entry much like you said.

    点赞 打赏 评论
  • duangan1945 2018-12-13 22:11

    No. Channels are FIFO buffers, full stop. That is how channels work and their only purpose. If you only want the latest value, consider just using a single variable protected by a mutex; write to it whenever new data comes in, and whenever you read it, you will always be reading the latest value.

    点赞 打赏 评论
  • dongqiang5932 2018-12-14 05:59

    Channels serves a specific purpose. You might want to use a code that is inside a lock and update the variable whenever new value is to be set.

    This way reciever will always get the latest value.

    点赞 打赏 评论

相关推荐 更多相似问题