我从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秒后读取。
有没有一种方法可以让通道一次只包含一个值,这样我就只得到我感兴趣的数据,而通道不会使用不必要的内存(尽管内存是我最不担心的)?
7条答案
按热度按时间ljsrvy3e1#
通道最好被认为是队列(FIFO)。因此你不能跳过它。但是有一些库可以做类似这样的事情:https://github.com/cloudfoundry/go-diodes是一个原子环形缓冲区,它将覆盖旧数据。如果愿意,您可以设置一个较小的大小。
尽管如此,听起来您并不需要队列(或环形缓冲区),您只需要一个互斥锁:
这使用了一个
RWMutex
,这意味着许多东西可以同时从它读取,而只有一个东西可以写入。2uluyalo2#
不。通道是FIFO缓冲区,句号。这就是通道的工作方式,也是它们唯一的用途。如果你只想要最新的值,考虑只使用一个受互斥保护的变量;每当有新数据进入时就向其写入,每当读取它时,总是阅读最新的值。
4si2a6ki3#
通道有特定的用途。您可能希望使用锁内部的代码,并在设置新值时更新变量。
这样,接收方将始终获得最新的值。
js81xvg64#
您无法直接从一个通道获得该值,但可以为每个值使用一个通道,并在出现新值时得到通知:
如果不需要通知新值,可以尝试读取Channels inside channels pattern in Golang。
wswtfjt75#
试用此软件包https://github.com/subbuv26/chanup
它允许生产者用最新的值更新通道,最新的值替换最新的值。并且生产者不会被阻塞。(这样,过时的值会被覆盖)。因此,在消费者端,总是只有最新的项被读取。
t5zmwmid6#
解决这个问题还有另一种方法(窍门)
发送方工作速度更快:如果channel_length〉1,则发送方删除信道
接收器工作较慢:
或者,我们可以从接收方删除旧消息(阅读消息,如删除它)
q43xntqr7#
这里有一个优雅的通道解决方案,如果你不介意再增加一个通道和goroutine,你可以引入一个无缓冲通道和一个goroutine,它会尝试把最新的值从你的通道发送给它: