I do not understand when you need to close the MySQL connection.

package main import ( ... _ "github.com/go-sql-driver/mysql" ) func main() { db, err := sql.Open(...) http.HandleFunc("/", TestFunc) http.ListenAndServe(":8080", nil) db.Close() } 

In this example, will the connection be closed or not? As I understand it, the main function will not complete as long as ListenAndServe is running, and you need to close the connection at the end of each HandleFunc ?

  • "you need to close the connection at the end of each HandleFunc". Doesn't your statement indicate that the connection needs to be opened in HandleFunc? As for the rest, the connection pool should deal with the connection resources, which is implemented in the package. Those. This should not be a concern for your functionality. - mals

3 answers 3

  1. In this example, will the connection be closed or NO?

In this formulation of the problem - no, the connection will not be closed.

  1. As I understand it, the main function will not complete as long as ListenAndServe is running.

Yes, main will not complete. Moreover, it will not end in principle, since the only option to terminate the program after http.ListenAndServer (if you do not use additional libraries) is to send SIGTERM to it, after which it simply ends without worrying about the execution of the last directive from main . By the way, defer db.Close() will not work either, because main not completed.

  1. and you need to close the connection at the end of each HandleFunc?

The connection does not need to close at all. Inside db/sql connection pool is used , i.e. Once you db.SetMaxIdleConns and db.SetMaxOpenConns you can forget about managing connections.

If it is critical for you to close the connection, the only option is to intercept the commands for termination and close the connection. Code like this

 imports ( ... _ "github.com/go-sql-driver/mysql" "os" "os/signal" "syscall" ) func main() { db, err := sql.Open(...) c := make(chan os.Signal, 2) signal.Notify(c, os.Interrupt, syscall.SIGTERM) go func() { <-c db.Close() os.Exit(1) }() http.HandleFunc("/", TestFunc) http.ListenAndServe(":8080", nil) } 

But, again, in reality this is a useless exercise.

    Use the special operator defer, which allows you to postpone the call to the specified function until the current one is completed:

     func main() { db, err = sql.Open("mysql", "...") if err != nil { panic(err.Error()) } defer db.Close() http.HandleFunc("/", TestFunc) http.ListenAndServe(":8080", nil) } 

    http://golang-book.ru/chapter-07-functions.html

    • I do not see the answer to the question! I know what a defer is and how it works, the question is different. - bsbak

    If closing a connection with MySQL is necessary, then this can be implemented by creating two handler functions HandleFuncBefore and HandleFuncAfter .

    The idea is simple: in the first we open the connection, in the second we close it, and the other handler functions, in fact, must inherit HandleFuncBefore and call HandleFuncAfter after processing.

    An example using the Gin framework, it is possible to describe the idea a little easier:

     // код для версии v1.0-rc.2 func DatabaseConnection() gin.HandlerFunc { return func(c *gin.Context) { // Выполнение кода перед запросом (HandleFuncBefore) db, err = sql.Open("mysql", "...") if err != nil { panic(err.Error()) } c.Set("db", db) // Обработка текущего запроса c.Next() // Выполнение кода после запроса (HandleFuncAfter) db.Close() } } func main() { r := gin.New() r.Use(DatabaseConnection()) r.GET("/test", func(c *gin.Context) { db := c.MustGet("db").(*sql.DB) // использование db }) // Запуск сервера Gin r.Run(":8080") }