英文:
Defer called in go routine
问题
我相信我对正常情况下的defer理解得很好,比如在这个问题中列出的情况https://stackoverflow.com/questions/24720097/golang-defer-behavior。然而,当defer在不返回的goroutine中调用时,我有点困惑发生了什么。以下是相关的代码。
func start_consumer() {
conn, _ := amqp.Dial("amqp://username:password@server.com")
//defer conn.Close()
ch, _ := conn.Channel()
//defer ch.Close()
q, _ := ch.QueueDeclare(
"test", // name
true, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
_ = ch.Qos(
3, // prefetch count
0, // prefetch size
false, // global
)
forever := make(chan bool)
go func() {
for {
msgs, _ := ch.Consume(
q.Name, // queue
"", // consumer
false, // ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
d.Ack(true)
}
time.Sleep(1 * time.Second)
}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever
}
这个函数是从以下位置调用的:
go start_consumer()
这可能是我对通道工作原理的误解,但我认为forever不会返回,因为它正在等待一个值传递给它。
英文:
I believe I understand defer well in the normal use cases. Such as the one listed in this question https://stackoverflow.com/questions/24720097/golang-defer-behavior. However I am a little perplexed as to what is happening when defer is called inside a goroutine that does not return. Here is the code in question.
func start_consumer() {
conn, _ := amqp.Dial("amqp://username:password@server.com")
//defer conn.Close()
ch, _ := conn.Channel()
//defer ch.Close()
q, _ := ch.QueueDeclare(
"test", // name
true, // durable
false, // delete when unused
false, // exclusive
false, // no-wait
nil, // arguments
)
_ = ch.Qos(
3, // prefetch count
0, // prefetch size
false, // global
)
forever := make(chan bool)
go func() {
for {
msgs, _ := ch.Consume(
q.Name, // queue
"", // consumer
false, // ack
false, // exclusive
false, // no-local
false, // no-wait
nil, // args
)
for d := range msgs {
log.Printf("Received a message: %s", d.Body)
d.Ack(true)
}
time.Sleep(1 * time.Second)
}
}()
log.Printf(" [*] Waiting for messages. To exit press CTRL+C")
<-forever
}
This function is called from
go start_consumer()
This is likely a misunderstanding by me how channels work but I though forever would not return since it's waiting for a value to be passed to it.
答案1
得分: 7
《Go Blog》中的延迟、恐慌和恢复一文在前面的问题中提到了延迟语句的工作原理。
延迟语句会将一个函数调用推入一个列表中。保存的函数调用列表会在包围它的函数返回后执行。延迟语句通常用于简化执行各种清理操作的函数。
在你的情况下,由于goroutine不会返回,保存的延迟调用列表将永远不会被执行。因此,在这种情况下,延迟语句是不必要的。
英文:
The Go Blog's Defer, Panic, and Recover post referenced in the previous question does a great job explaining how defer statements work.
> A defer statement pushes a function call onto a list. The list of saved calls is executed after the surrounding function returns. Defer is commonly used to simplify functions that perform various clean-up actions.
In your case since the goroutine does not return, the list of deferred calls will never be run. This makes the defer statement unnecessary in this context.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论