Go 更新未读通道数据

Go 更新未读通道数据,go,Go,有没有办法用更多最新数据更新发送到频道的未读数据 我有一个goroutine(制作人)和一个频道,该频道向另一个goroutine(消费者)提供进度更新。在某些情况下,更新进度可能比使用者使用更新消息的速度快得多 这会给我带来问题,因为我可以: 阻止向通道发送数据。这意味着,如果使用者读取数据的速度很慢,更新goroutine的过程就会完全阻塞——这是不应该的 频道已满时,不要阻止发送和跳过进度更新。这意味着消费者总是在读取旧的数据 举个例子,我可能有这样的想法: 进度报告goroutine

有没有办法用更多最新数据更新发送到频道的未读数据

我有一个goroutine(制作人)和一个频道,该频道向另一个goroutine(消费者)提供进度更新。在某些情况下,更新进度可能比使用者使用更新消息的速度快得多

这会给我带来问题,因为我可以:

  • 阻止向通道发送数据。这意味着,如果使用者读取数据的速度很慢,更新goroutine的过程就会完全阻塞——这是不应该的
  • 频道已满时,不要阻止发送和跳过进度更新。这意味着消费者总是在读取旧的数据
举个例子,我可能有这样的想法:

进度报告goroutine:向频道发布“1%”
进度报告goroutine:将“2%”发布到频道
进度报告goroutine:将“3%”发布到频道
进度消耗goroutine:从通道读取“1%”、“2%”和“3%”。“1%和“2%”是过时的信息。


有没有办法更新未读的频道数据?或者有没有更好的办法解决这个问题?

每次向频道发送值之前,只需清除频道即可

换句话说,当您发送3%时,3%将成为通道中的唯一值


您可以将缓冲区长度设置为1,因此只需使用
即可,每次在将值发送到通道之前清除通道

换句话说,当您发送3%时,3%将成为通道中的唯一值


您可以使您的频道的缓冲区长度为1,因此只需使用
您就可以将一些值存储在受
RWMutex
保护的全局变量中,它保持进度。生成器更新它。使用者读取并显示

您还可以对长度为1的通道进行非阻塞写入:

var c = make(chan struct{}, 1)
select {
case c <- struct{}{}:
default:
}
var c=make(chan结构{},1)
挑选{

案例c您可以在受
RWMutex
保护的全局变量中存储一些值,它保持进度。生成器更新它。使用者读取并显示

您还可以对长度为1的通道进行非阻塞写入:

var c = make(chan struct{}, 1)
select {
case c <- struct{}{}:
default:
}
var c=make(chan结构{},1)
挑选{
案例c<代码>主包装
输入“fmt”
func main(){
//在这种情况下,通道缓冲区必须为1
var ch=制造(成交量,1)
//当通道未使用且您希望更新通道上的值时
生产渠道(ch,1)
生产渠道(ch,2)
fmt.Println(consumerfromchannel(ch))//打印2
//当频道已被消费,而您正在产生新的价值时
生产渠道(ch,3)
消费频道(ch)
生产渠道(第4章)
fmt.Println(consumerfromchannel(ch))//打印4
}
func生产频道(ch chan int,v int){
挑选{
包装箱
主包装箱
输入“fmt”
func main(){
//在这种情况下,通道缓冲区必须为1
var ch=制造(成交量,1)
//当通道未使用且您希望更新通道上的值时
生产渠道(ch,1)
生产渠道(ch,2)
fmt.Println(consumerfromchannel(ch))//打印2
//当频道已被消费,而您正在产生新的价值时
生产渠道(ch,3)
消费频道(ch)
生产渠道(第4章)
fmt.Println(consumerfromchannel(ch))//打印4
}
func生产频道(ch chan int,v int){
挑选{

case如何使用一个并发映射来存储所有入站对象的版本,其中0表示默认版本

import "sync"
var Versions sync.Map = sync.Map{}
type Data struct {
    Payload interface{}
    Version int
    ID int
}

func produce(c chan Data) {
    for {
        data := produceData()
        if hasNewVersion(data) {
            Versions.Store(data.ID, data.Version)
        }
        c <- data 
    }
}

func consume(c chan Data) {
    for {
        select {
        case val:= <- c:
            if ver, ok := Versions.Load(val.ID); ok {
                if ver.(int) == val.Version {
                    // process
                }
            }
        }
    }
}
导入“同步”
var Versions sync.Map=sync.Map{}
类型数据结构{
有效负载接口{}
版本int
ID int
}
func product(c chan数据){
为了{
数据:=生产数据()
如果有新版本(数据){
Versions.Store(data.ID,data.Version)
}

c如何使用一个并发映射来存储所有入站对象的版本,其中0表示默认版本

import "sync"
var Versions sync.Map = sync.Map{}
type Data struct {
    Payload interface{}
    Version int
    ID int
}

func produce(c chan Data) {
    for {
        data := produceData()
        if hasNewVersion(data) {
            Versions.Store(data.ID, data.Version)
        }
        c <- data 
    }
}

func consume(c chan Data) {
    for {
        select {
        case val:= <- c:
            if ver, ok := Versions.Load(val.ID); ok {
                if ver.(int) == val.Version {
                    // process
                }
            }
        }
    }
}
导入“同步”
var Versions sync.Map=sync.Map{}
类型数据结构{
有效负载接口{}
版本int
ID int
}
func product(c chan数据){
为了{
数据:=生产数据()
如果有新版本(数据){
Versions.Store(data.ID,data.Version)
}

c这是通道本身无法解决设计问题的情况之一。相反,创建一个包含互斥和整数的结构。根据具体要求,您可能会将通道仅用于信令目的。使用通道仅用于信令目的非常有意义,谢谢@zerkms。不过有一个简单的问题:do如果只有一个例程在写,而另一个例程在读,那么我需要一个互斥体?看看Eugene的答案:他们完全解释了我的意思(尽管他们建议使用全局变量,而我的想法是用方法将所有内容封装在一个结构中)这是通道本身无法解决设计问题的情况之一。相反,请创建一个包含互斥和整数的结构。根据具体要求,您可能会将通道仅用于信令目的。使用通道仅用于信令目的非常有意义,谢谢@zerkms。不过,有一个简单的问题:是否这样做如果只有一个例程在写,而另一个例程在读,那么我需要一个互斥体。看看Eugene的答案:他们完全解释了我的意思(尽管他们建议使用一个全局变量,而我的想法是用方法将所有内容封装在一个结构中)谢谢Eugene。不过这可能是个愚蠢的问题:如果只有一个例程在写,而一个例程在读,我需要互斥吗?@Sam你完全需要。如果至少有一个例程在写,那么其他所有的东西都必须同步。这对大多数(所有)都有效具有线程支持的语言,而不仅仅是go。是的,有专门的读写互斥。请看一看。我还更新了配方-如何仅使用一个通道来解决任务。@EugeneLisitsky鉴于他们只有一个读写器,可能有理由只使用标准的互斥