如何将defer与http.ListenAndServe结合使用?

huangapple go评论76阅读模式
英文:

How to use defer in combination with http.ListenAndServe?

问题

在使用Go语言中的http.ListenAndServe()时,会导致阻塞的情况,似乎只能通过终止进程来停止应用程序。这似乎会跳过处理我的defer语句。请参考下面的代码。当我终止应用程序时,数据库没有关闭。如何确保我的defer语句会被执行?

func main() {
  db := NewDB(DBFILENAME)
  defer db.Close()
  http.HandleFunc("/", handler)
  http.ListenAndServe(":80", nil)
}
英文:

When using http.ListenAndServe() in Go, this results in a blocking situation where the application, apparently, can only be stopped by killing it. This seems to skip processing my defer statements. Please see the code below. When I kill the application the db is not closed. How can I make sure my defer statement will be run?

func main() {
  db := NewDB(DBFILENAME)
  defer db.Close()
  http.HandleFunc("/", handler)
  http.ListenAndServe(":80", nil)
}

答案1

得分: 3

defer语句只有在包含它们的函数返回时才会执行。当你终止主函数时,它并没有返回。所以你需要使用信号和通道。

这是一个很好的链接,解释了相同的问题:https://www.socketloop.com/tutorials/golang-intercept-ctrl-c-interrupt-or-kill-signal-and-determine-the-signal-type。

我在我的上一个项目中遇到了同样的问题。我在我的项目wshare中实现了类似的解决方案。

在你的情况下,你可以尝试像这样的代码:

ch := make(chan os.Signal, 3)

signal.Notify(ch, os.Interrupt, syscall.SIGTERM, syscall.SIGINT)

go func() {
    signalType := <-ch
    signal.Stop(ch)
    log.Println("Exit command received. Exiting...")

    // 在终止之前,这是一个将所有内容刷新到磁盘的好地方
    db.Close()
    log.Println("Signal type: ", signalType)

    os.Exit(0)
}()
英文:

defer statements get executed only when the function enclosing them returns. Your main function is not returning when you kill it. So you need to use signals and channels.

This is a good link explaining the same https://www.socketloop.com/tutorials/golang-intercept-ctrl-c-interrupt-or-kill-signal-and-determine-the-signal-type .

I faced the same problem with my last project. I implemented a similar solution in my project wshare .

In your case, you can try something like

     ch := make(chan os.Signal, 3)

     signal.Notify(ch, os.Interrupt,syscall.SIGTERM,syscall.SIGINT)


     go func() {
             signalType := &lt;-ch
             signal.Stop(ch)
             log.Println(&quot;Exit command received. Exiting...&quot;)

             // this is a good place to flush everything to disk
             // before terminating.
             db.Close()
             log.Println(&quot;Signal type : &quot;, signalType)

             os.Exit(0)

     }()

答案2

得分: 3

下一个 Go 发布版本 1.8 中的 HTTP 包将会有一个新的 Shutdown 函数,用于优雅地关闭服务器。https://beta.golang.org/pkg/net/http/#Server.Shutdown
我认为 defer 会起作用。

英文:

The HTTP package in the next go release 1.8 will have a new Shutdown function that gracefully shuts down the server . https://beta.golang.org/pkg/net/http/#Server.Shutdown
I suppose that defer will work then.

huangapple
  • 本文由 发表于 2017年1月11日 23:01:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/41594137.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定