Golang代码组织又需要调用db.Close()吗?

时间:2018-06-10 20:34:09

标签: go

到目前为止,Go最困难的部分是了解如何组织代码。它的表面看起来非常简单,但每次我尝试做任何事情时都会遇到循环导入或类似“导出的func Start返回未导出的类型models.dbStore,这可能很烦人”。

使用以下代码如何调用db.Close()或者我真的不明白我应该如何向我的模型提供数据库。这就是我所拥有的:

App.go

package app

import (
    "database/sql"

    // Comment
    _ "github.com/mattn/go-sqlite3"
)

var (
    // DB The database connection
    db *sql.DB
)

// Setup Sets up the many many app settings
func Setup() {
    d, err := sql.Open("sqlite3", "./foo.db")
    if err != nil {
        panic(err)
    }

    // TODO: How does the DB get closed?
    // defer db.Close()
    db = d
}

// GetDB Returns a reference to the database
func GetDB() *sql.DB {
    return db
}

Users.go

package models

import (
    "github.com/proj/org/app"
)

// User struct
type User struct {
    ID int
}

// CreateUser Creates a user
func (u *User) CreateUser() (int64, error) {

    // For the sake of brevity just make sure you can
    // "connect" to the database
    if err := app.GetDB().Ping(); err != nil {
        panic(err)
    }

    return 1234, nil
}

main.go

package main

import (
    "fmt"
    "net/http"

    _ "github.com/mattn/go-sqlite3"
    "github.com/proj/org/app"
    "github.com/proj/org/models"
)

func homeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "You are home")
}

func subscribeHandler(w http.ResponseWriter, r *http.Request) {
    fmt.Fprintf(w, "Subscribing...")
    u := models.User{}

    u.CreateUser()

}

func main() {
    fmt.Println("Running")

    app.Setup()

    http.HandleFunc("/", homeHandler)
    http.HandleFunc("/subscribe", subscribeHandler)

    err := http.ListenAndServe(":9090", nil)
    if err != nil {
        panic(err)
    }
}

我考虑过做app.Shutdown(),但这对我最常用的CTRL-C用例不起作用。看来如果我不关闭数据库,数据库连接就会增长......只是想了解。

1 个答案:

答案 0 :(得分:2)

没有必要关闭数据库。

  

返回的数据库对于多个goroutine和并发使用是安全的   维护自己的空闲连接池。因此,Open功能   应该只召唤一次。很少需要关闭数据库。

来自:https://golang.org/pkg/database/sql/#Open

当你的程序退出然后关闭任何打开的连接时,它不会在等待你的程序再次启动的以太网中保持打开状态,所以当你按CTRL-C应用程序时不要担心连接“增长”。

但是,如果您仍想要关闭它,那么您可以像导出CloseDB一样导出GetDB功能。

App.go

// ...

func CloseDB() error {
    return db.Close()
}

main.go

// ...

func main() {
    // ...

    app.Setup()
    defer app.CloseDB()

    // ...

}