kra*_*r65 -1 parallel-processing concurrency channel multiprocessing go
我开始使用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"
}
}
Run Code Online (Sandbox Code Playgroud)
这很好,但是传感器会生成大量数据,而我总是只对最新数据感兴趣.但是,使用此设置,它仅在每个循环中读出下一个项目,这意味着如果某个点的通道包含20个值,则仅在10秒后读取最新值.
有没有办法让一个通道一次只包含一个值,这样我总是只得到我感兴趣的数据,并且通道没有使用不必要的内存(尽管内存是我最不担心的)?
欢迎所有提示!
通道最好被认为是队列(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
}
Run Code Online (Sandbox Code Playgroud)
这使用了一个RWMutex意味着许多东西可以同时读取它,而只有一件东西可以写.它会像你说的那样存储一个条目.
不。通道是 FIFO 缓冲区,句号。这就是渠道的工作方式及其唯一目的。如果您只想要最新的值,请考虑只使用受互斥锁保护的单个变量;每当有新数据进入时写入它,无论何时读取它,您将始终读取最新值。