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

如何始终从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.

    评论
查看更多回答(2条)

报告相同问题?

悬赏问题

  • ¥15 求苹果推信imessage批量推信技术
  • ¥15 ubuntu 22.04 系统盘空间不足。隐藏的docker空间占用?(相关搜索:移动硬盘|管理系统)
  • ¥15 利用加权最小二乘法求亚马逊各类商品的价格指标?怎么求?
  • ¥15 c++ word自动化,为什么可用接口是空的?
  • ¥15 Matlab计算100000*100000的矩阵运算问题:
  • ¥50 VB6.0如何识别粘连的不规则的数字图片验证码
  • ¥16 需要完整的这份订单所有的代码,可以加钱
  • ¥15 Stata数据分析请教
  • ¥15 请教如何为VS2022搭建 Debug|win32的openCV环境?
  • ¥15 关于#c++#的问题:c++如何使用websocketpp实现websocket接口调用,求示例代码和相关资料