select - 戈朗 : select statement exits when it shouldn't

标签 select go channel channels

我正在尝试创建一个程序,每 3 日、8 日打印一次 "Eat""Work""Sleep",和第 24 秒。这是我的代码:

package main

import (
"fmt"
"time"
)

func Remind(text string, delay time.Duration) <-chan string { //channel only for receiving strings
    ch := make(chan string) // buffered/unbuffered?
    go func() {
        for {
            msg := "The time is " + time.Now().Format("2006-01-02 15:04:05 ") + text
            ch <- msg
            time.Sleep(delay) // waits according to specification
        }
    }()
    return ch
}

func main() {
    ch1 := Remind("Eat", 1000*1000*1000*3) // every third second    
    ch2 := Remind("Work", 1000*1000*1000*8) // every eighth second
    ch3 := Remind("Sleep", 1000*1000*1000*24) // every 24th second
    select { // chooses one channel that is not empty. Should run forever (?)
        case rem1 := <-ch1:
            fmt.Println(rem1)
        case rem2 := <-ch2:
            fmt.Println(rem2)
        case rem3 := <-ch3:
            fmt.Println(rem3)
    }
}

它的问题是它在打印时间后立即停止运行,然后是 “Eat”。在我读过的其他示例中,select 语句会一直持续下去。为什么现在不呢?

最佳答案

我不知道您在哪里读到过 select 会永远持续下去,但事实并非如此。

一旦 case 被执行,select 语句就“完成”了。如果 case 中指定的通信操作都不能继续并且没有default 分支,select 将阻塞,只要任何 com。操作可以继续。但是一旦一个case被执行,select就不会重复了。

阅读规范中的相关部分:Select statements .

把它放在无穷无尽的 for 中,让它永远重复:

for {
    select { // chooses one channel that is not empty. Should run forever (?)
    case rem1 := <-ch1:
        fmt.Println(rem1)
    case rem2 := <-ch2:
        fmt.Println(rem2)
    case rem3 := <-ch3:
        fmt.Println(rem3)
    }
}

作为旁注:

您可以创建 time.Duration使用 time 中的常量值更容易包裹:

ch1 := Remind("Eat", 3*time.Second)    // every third second
ch2 := Remind("Work", 8*time.Second)   // every eighth second
ch3 := Remind("Sleep", 24*time.Second) // every 24th second

您可能还想查看 time.Ticker用于与您的 Remind() 函数类似的任务的类型。

关于select - 戈朗 : select statement exits when it shouldn't,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36327358/

相关文章:

git - 如何维护原始文件?

go - 无法安装 ipfs

go - 如何从另一个文件夹导入主文件夹

installation - 未找到软件包错误 : The following packages are not available from current channels:

xml - 如何选择包含@符号(at符号)的属性

sql - SQL中的错误(SELECT和LEFT Join)如何给第一个表id?

javascript - 旧输入数组和动态字段 - Laravel - Blade

python - MySQL 和 Python Select 语句问题

Golang : Interrupting infinite polling having time. 休眠

go - 如何等到缓冲 channel (信号量)为空?