因此,我开始迷恋Go,并且对go例程着迷。现在,我编写了一个简单的测试,以查看在连续打印输出时是否可以更改变量的值。
我现在有以下代码:
package main
import (
"fmt"
"time"
)
func change(c chan float64) float64 {
time.Sleep(2 * time.Second)
return 2.5
}
func main() {
s := 1.1
c := make(chan float64)
go change(c)
s = <-c
for {
fmt.Println(s)
time.Sleep(100 * time.Millisecond)
}
}
不幸的是,它以错误结尾:
fatal error: all goroutines are asleep - deadlock!
goroutine 1 [chan receive]:
main.main()
/home/kramer65/repos/go/src/messing_around/main.go:19 +0x7d
exit status 2
我四处搜索,发现当主函数结束而goroutine尚未结束时,就会发生这种死锁。但是由于我有一个无限循环,所以我不知道我的代码还有什么问题。
有人能启发我这段代码有什么问题吗?在不断地打印出来的同时,如何更改变量的值?欢迎所有提示!
答案 0 :(得分:1)
看来您可能对频道和常规节目有误解。
该行:
go change(c)
似乎表明函数change
将要写入c
。但是,它最终只是在一段时间后返回一个值。
此值(2.5
)在任何地方都不会收到。另外,c
不会写入任何地方。我怀疑您打算将2.5
写入通道c
。其语法如下:
c<-2.5
因此,如果将change
函数更改为:
func change(c chan float64) {
time.Sleep(2 * time.Second)
c <- 2.5
}
您不应再看到僵局。请注意,我不再返回float64
。
我做了一个操场来确保这一点:https://play.golang.org/p/SgLiUmPpcAZ
更新评论
1.1
将始终被通道的值覆盖。但是,如果您要打印s
的初始值(如注释中所述),则必须稍微改变流程并使用select
语句:
package main
import (
"fmt"
"time"
)
func change(c chan float64) {
time.Sleep(2 * time.Second)
c <- 2.5
}
func main() {
s := 1.1
c := make(chan float64)
go change(c)
for {
select {
case s = <-c:
default:
// c isn't ready yet
}
fmt.Println(s)
time.Sleep(100 * time.Millisecond)
}
}
现在您有了一个select
语句,您也可以将其与time.Ticker
一起使用:
ticker := time.NewTicker(100 * time.Millisecond)
for {
select {
case s = <-c:
case <-ticker.C:
fmt.Println(s)
default:
// c isn't ready yet
}
}