在go例程中调用延迟

在go例程中调用延迟,go,Go,我相信我在正常的用例中很理解延迟。比如这个问题中列出的那个。然而,我有点困惑,当在一个不返回的goroutine中调用defer时会发生什么。这是有问题的代码 func start_consumer() { conn, _ := amqp.Dial("amqp://username:password@server.com") //defer conn.Close() ch, _ := conn.Channel() //defer ch.Close()

我相信我在正常的用例中很理解延迟。比如这个问题中列出的那个。然而,我有点困惑,当在一个不返回的goroutine中调用defer时会发生什么。这是有问题的代码

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博客文章很好地解释了延迟声明的工作原理

defer语句将函数调用推送到列表上。保存的调用列表在周围函数返回后执行。Defer通常用于简化执行各种清理操作的函数


在您的情况下,由于goroutine不会返回,因此延迟调用列表将永远不会运行。这使得延期声明在此上下文中不必要。

您到底在问什么?您期望的是什么行为?发生了什么?很简单,当函数返回时,延迟语句就会执行。如果函数不返回,延迟语句就不会执行。我想知道
defer
语句是否与
SIGTERM
信号相关?例如:您正在打开一个文件并收到一个
SIGTERM
信号-这会自动启动
defer
功能以正常关闭,还是应该手动监听
SIGTERM
信号以调用defer语句?并回答我自己的问题:当收到
SIGTERM
时,或调用
os.Exit
,则不会执行延迟调用。您必须手动调用已延迟的函数才能执行它们。事实上,当你再也不回电话时,推迟打电话是没有意义的。
go start_consumer()