首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >在侦听信道和循环处理时重写通道

在侦听信道和循环处理时重写通道
EN

Stack Overflow用户
提问于 2018-07-02 13:13:02
回答 2查看 113关注 0票数 2

在尝试几个频道实验时,我想出了下面的代码:

代码语言:javascript
复制
var strChannel = make(chan string, 30)
var mutex = &sync.Mutex{}

func main() {

    go sampleRoutine()

    for i := 0; i < 10; i++ {
        mutex.Lock()
        strChannel <- strconv.FormatInt(int64(i), 10)
        mutex.Unlock()
        time.Sleep(1 * time.Second)
    }

    time.Sleep(10 * time.Second)
}

func sampleRoutine() {
/*  A: for msg := range strChannel{*/
/*  B: for {
        msg := <-strChannel*/
        log.Println("got message ", msg, strChannel)
        if msg == "3" {
            mutex.Lock()
            strChannel = make(chan string, 20)
            mutex.Unlock()
        }
    }
}

基本上在这里,在听给定的通道时,我将信道变量在特定的条件下分配给一个新的通道(当msg == 3时)。

当我在注释块B中使用代码时,它按预期工作,即循环移动到新创建的通道并打印4-10。

然而,注释块A,我认为这只是一种不同的方式写循环不工作,即在打印"3“,它停止。

有人能告诉我这种行为的原因吗?

在这样的代码中,一个例行监听通道,创建一个新的通道安全吗?

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2018-07-02 14:02:25

在Go中,for语句在循环开始前计算range右侧的值。

这意味着更改range右侧变量的值不会产生任何影响。因此,在您的代码中,在变体A中,msg总是在原始通道上迭代,并且从未改变过。在Varaint中,它按照预期的方式工作,因为每次迭代都要对通道进行评估。

这个概念有点棘手。这并不意味着您不能在slicemap的右侧修改range的项。如果深入研究它,您会发现在Go中,mapslice存储一个指针,而修改它的项不会更改该指针,因此它会产生效果。

array的情况下,这就更加棘手了。修改arrayrange右侧的项没有任何影响。这是由于Go将数组存储为值的机制。

操场示例:https://play.golang.org/p/wzPfGHFYrnv

票数 2
EN

Stack Overflow用户

发布于 2018-07-02 13:35:31

  1. 从通道发送和读取不需要受互斥保护:它们在通道上充当同步原语(这是发送/接收的主要思想之一)。
  2. 变量A和B之间没有区别,因为您没有关闭通道。但是..。
  3. 在迭代旧通道的同时将一个新通道辞职到strChannel是错误的。别干那事。即使是B变体也不行。将range strChannel想象为“请在当前存储在变量strChannel中的通道中的值范围内”。这个范围将“在原始通道上继续”,并且在同一个变量中存储一个新通道不会改变这一点。避免这样的代码!
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/51137056

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档