php小编西瓜认为,"由 time.AfterFunc() 递归调用的 goroutine 的设计很糟糕"这句话反映了一种不合理的设计思路。在并发编程中,递归调用的 goroutine 可能导致资源消耗过大,甚至引发死锁和内存溢出等问题。因此,应该谨慎使用递归调用,并考虑使用其他替代方案来解决问题,以确保程序的性能和稳定性。在编写代码时,我们应该时刻关注设计的合理性,避免出现不必要的问题。
我有一个小型 http 应用程序 (A)。在启动时,它调用另一个 http 服务 (B) 来验证许可证,如果许可证正常,则 http 服务器 (A) 启动。如果验证失败A则出现致命错误退出
许可证检查每 24 小时进行一次
每 24 小时递归创建一个新的 goroutine 会被认为是一个糟糕的设计吗?检查下面我的代码。之前的goroutine会关闭还是继续运行然后n个goroutine互相调用而结束
每个新的 goroutine 是从主 goroutine 调用还是从子 goroutine 调用?
func Request(retry bool) error { // request and verify license (external http service) err := verify_license() if err != nil { return err } if retry { // Renew verification timeout (renew license every 24 hours) time.AfterFunc(LICENSE_TIMEOUT, func(){ request_retry() }) } return nil } func request_retry(){ for i := 0; i < LICENSE_RETRY; i++ { if err := v.Request(false); err == nil { break } time.Sleep(LICENSE_RETRY_TIMEOUT) } time.Sleep(LICENSE_TIMEOUT) v.Request(true) }
if err := license_verify.Request(true); err != nil { log.Fatal(err.Error()) }
也许你可以重新思考问题的设计。例如:
func main() { if !checkLicense() { log.Fatal("license check failed") } srv := http.Server{} // ctx, cancel := context.WithCancel(context.Background()) defer cancel() go func() { for { select { case <-ctx.Done(): // in case you want to instal signal handlers etc return case <-time.After(24 * time.Hour): if !checkLicense() { cancel() // or srv.Shtdown, really depends on you } } } }() if err := srv.ListenAndServe(); err != nil { log.Fatal(err) } } func checkLicense() bool { // add retries per request here }
基本上,它的作用是创建一个 goroutine,定期检查并在出现问题时通知上下文或通道。
如果我正确理解了这个问题,那么你只需要保持简单即可。一个构建块是请求失败时重试。除此之外,是 24 小时重试。最后一层是,如果检查失败,则对其做出反应。您可以使用上下文、频道或您真正喜欢的任何内容
以上是由 time.AfterFunc() 递归调用的 goroutine 的设计很糟糕的详细内容。更多信息请关注PHP中文网其他相关文章!