英文:
Why is my custom "Timeout waiting on channel" not working and how to make it work?
问题
我正在尝试制作自己的自定义“通道超时”。更准确地说,是其中的time.After
函数。换句话说,我正在尝试实现以下代码:
select {
case v := <-c:
fmt.Println("Value v:", v)
case <-time.After(1 * time.Second):
fmt.Println("Timeout")
}
但不幸的是,我遇到了一个问题。
我的实现是:
func waitFun(wait int) chan int {
time.Sleep(time.Duration(wait) * time.Second)
c := make(chan int)
c <- wait
return c
}
func main() {
c := make(chan int)
go func() {
time.Sleep(3 * time.Second)
c <- 10
}()
select {
case v := <-c:
fmt.Println("Value v:", v)
case <-waitFun(1):
fmt.Println("Timeout")
}
time.Sleep(4 * time.Second)
}
出现错误:all goroutines are asleep - deadlock!
。我理解在某个时刻,所有的goroutine(主goroutine和通过匿名函数引入的goroutine)都会进入休眠状态,但这是错误的原因还是其他原因?我的意思是,它不是“无限休眠”或“无限等待某些东西”,所以这不是死锁,对吗?此外,使用time.After
也会使goroutine进入休眠状态,对吗?我需要做哪些更改才能使程序正常工作?
英文:
I'm trying to make my own custom "Channel Timeout". More precisely, the time.After
function inside it. In other words, I'm trying to implement this:
select {
case v := <-c:
fmt.Println("Value v: ", v)
case <-time.After(1 * time.Second):
fmt.Println("Timeout")
}
But unfortunately I ran into a problem.
My implementation is:
func waitFun(wait int) chan int {
time.Sleep(time.Duration(wait) * time.Second)
c := make(chan int)
c <- wait
return c
}
func main() {
c := make(chan int)
go func() {
time.Sleep(3 * time.Second)
c <- 10
}()
select {
case v := <-c:
fmt.Println("Value v: ", v)
case <-waitFun(1):
fmt.Println("Timeout")
}
time.Sleep(4 * time.Second)
}
For some reason this doesn't work. The error is: all goroutines are asleep - deadlock!
. I understand that at some point all goroutines (main and the one introduced with an anonymous function) will go to sleep, but is this the reason for the error or something else? I mean, it's not "infinite sleep" or "infinite wait for something", so it's not a dead lock, right? Additionally, using time.After
also sleeps goroutines, right? What do I need to change to make my program work correctly?
答案1
得分: 2
select
语句在运行时会评估所有的情况,所以这段代码实际上会在开始监听任何通道之前等待waitFun
返回。你需要修改waitFun
函数,使其立即返回通道:
func waitFun(wait int) chan int {
c := make(chan int)
go func() {
time.Sleep(time.Duration(wait) * time.Second)
c <- wait
}()
return c
}
英文:
select
statement will evaluate all cases when it is run, so this code will actually wait for the waitFun
to return before it starts listening to any channels. You have to change the waitFun
to return the channel immediately:
func waitFun(wait int) chan int {
c := make(chan int)
go func() {
time.Sleep(time.Duration(wait) * time.Second)
c <- wait
}()
return c
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论