【问题标题】:Go f(...) versus : f(go func(){...}())Go f(...) 与 : f(go func(){...}())
【发布时间】:2022-01-09 06:16:09
【问题描述】:

我是否正确假设在 Go 语言中,这两种表述总是等价的?

func f() {
    // Do stuff
}
go f() 



func f() {
   go func(){
     // do stuff
   }()
) 

【问题讨论】:

  • 现在是(我更正了)
  • 所写的语句具有相同的结果。第一个通常是首选,因为调用者控制并发。
  • 但是,如果 f() 必须始终作为单独的进程调用,那么第二个公式会自动执行该任务。
  • 通常情况下可能并不总是需要并发,或者根据上下文以不同的方式构建同步可能更方便。约定通常是让调用者决定直接调用的函数何时需要并发,并且只根据需要调度 goroutine 作为实现细节的一部分。
  • 第一个公式允许调用者用其他代码将// do stuff括起来,等待// do stuff完成等。第二个公式可能是您实际问题的正确选择,但它是并非在所有情况下都是正确的选择。

标签: go closures goroutine


【解决方案1】:

这个问题基本上在 cmets 中得到了回答,但是虽然在简单的情况下,两个示例都做同样的事情,但根据实际目标是什么,一个可能比另一个更受欢迎。

cmets 提到的一个问题是允许您的代码用户决定并发性,而不是您(作者)决定。我认为这个经验法则通常是首选的,特别是对于编写包供他人使用的人(即使其他人可能在你自己的团队中)。我还在“互联网”的其他地方看到了这个经验法则,我认为这是因为在 Go 的早期,人们使用(和滥用)并发特性只是因为它们可用。例如,返回一个您将从中接收值的通道,而不仅仅是返回值。

另一个区别是,在上面的示例中,f() 可能无法关闭您在作为 goroutine 运行时可能希望访问的变量——您必须将所有内容作为参数传递给 f()。在第二个示例中,go func() {...} 中的匿名函数可以关闭 f() 中的某些内容。

我更喜欢第二种风格的一个例子是启动服务器。例如:

func (app *Application) start() {
    if app.HttpsServer != nil {
        go func() {
            err := app.HttpsServer.ListenAndServeTLS(
                app.Config.TLSCertificateFile,
                app.Config.TLSKeyFile)
            if err != nil && err != http.ErrServerClosed {
                // unexpected error
                log.Printf(log.Critical, "error with https server: %s", err)
            }
        }()
    }

    go func() {
        err := app.HttpServer.ListenAndServe()
        if err != nil && err != http.ErrServerClosed {
            // unexpected error
            log.Printf(log.Critical, "error with http server: %s", err)
        }
    }()
}

这里的意图是在main()中配置和控制Application,启动服务器(一个在https上,一个在http上),程序流程返回main()。在我的具体情况下,main() 等待来自操作系统的信号,然后关闭服务器并退出。两个 goroutine 都关闭了 app 并可以访问它包含的数据。这是“好”还是“坏”……谁知道呢,但对我来说效果很好。

所以本质上......“这取决于”。

【讨论】:

  • 请注意:我从来没有问过有好的配方还是坏的配方。我只是想问一下它们是否总是等价的。
  • 如果你以等效的方式使用它,它们应该本质上是等效的。但这是一个无用的答案,所以我举例说明了为什么你可能会选择一种或另一种方式。
猜你喜欢
  • 2018-03-21
  • 1970-01-01
  • 1970-01-01
  • 2018-06-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多