gpt4 book ai didi

go - goroutine 中 SMTP 的奇怪行为

转载 作者:数据小太阳 更新时间:2023-10-29 03:06:05 24 4
gpt4 key购买 nike

我对在 goroutine 中使用 SMTP 时发现的一些奇怪行为感到困惑。

尝试使用以下代码发送电子邮件时,我的 SendMail 函数启动(我可以看到一条日志消息)但从未完成。它只是挂起。

func main() {
go SendEmail("TEST")
for {}
}

但是,当我再次调用 SendMail 时 - 两封电子邮件均已成功发送。

func main() {
go SendEmail("TEST")
SendEmail("TEST")
for {}
}

谁能解释一下这是怎么回事?

注意这是一个非常简化的计划任务版本,因此是 while 循环

发送邮件的代码:

func SendEmail(message string) {
log.Print("Sending email")
from, password, to := "me@gmail.com", "PASSWORD", "me@gmail.com"

err := smtp.SendMail(
"smtp.gmail.com:587",
smtp.PlainAuth("", from, password, "smtp.gmail.com"),
from,
[]string{to},
[]byte(message),
)
if err != nil {
log.Fatal(err)
}
log.Print("Sending complete")
}

谢谢!

最佳答案

您应该将 for{} 替换为 select{}。永远不要创建空的 for{}

for{} 创建了一个永远旋转的循环,但由于循环中没有函数调用(或更准确地说,堆栈检查和/或分配),调度程序将永远无法deschedule 主 goroutine,这反过来会阻止你的其他 goroutine 被调度。 (这也可能会吃掉整个 CPU,因为您正忙于循环操作系统线程)

请参阅最后我关于 GOMAXPROCS 的注释。

通过在 go SendEmail("TEST") 之后立即调用 SendEmail("TEST"),运行时有机会(或者更确切地说,多次机会)安排您的在进入您的 for{} 循环之前要运行的其他 goroutine。

改为使用空选择 (select{}),主 goroutine 将无限期等待而不消耗任何 CPU,而是直接让步给调度程序。

关于 GOMAXPROCS

如果您的 GOMAXPROCS 为 1(Go 1.5 之前的默认值),您将只有一个操作系统线程(至少对于运行的 goroutines),如果您有一个忙循环,这将阻止任何其他 goroutines 运行。如果你有 GOMAXPROCS > 1 运行时仍然可以调度其他 goroutines,因为运行 goroutines 的线程不止一个,但你不应该依赖它。相反,您应该删除任何繁忙的循环。

关于go - goroutine 中 SMTP 的奇怪行为,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37636665/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com