donglu8779 2018-06-10 20:34
浏览 445
已采纳

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

So far the hardest part of Go has been understanding how to organize code. It seems incredibly simple on it's face but every time I've tried to do anything I run into circular imports or things like "exported func Start returns unexported type models.dbStore, which can be annoying to use".

Using the following code how do I call db.Close() or am I really not understanding how I'm supposed to provide the database to my models. Here's what I've got:

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)
    }
}

I thought about doing a app.Shutdown() but that wouldn't work for my most normal use case which is CTRL-C. It would seem if I don't close the database the DB connections would just grow... Just trying to understand.

  • 写回答

1条回答 默认 最新

  • douhuan1950 2018-06-10 21:27
    关注

    It's not necessary to close the DB.

    The returned DB is safe for concurrent use by multiple goroutines and maintains its own pool of idle connections. Thus, the Open function should be called just once. It is rarely necessary to close a DB.

    From: https://golang.org/pkg/database/sql/#Open

    When your program exits then any open connection is closed, it does not stay open somewhere in the ether awaiting your program to start again, so do not worry about the connections "growing" when you CTRL-C your app.


    If, however, you still want to close it, then you can just export a CloseDB function the same way you do with GetDB.

    App.go

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

    main.go

    // ...
    
    func main() {
        // ...
    
        app.Setup()
        defer app.CloseDB()
    
        // ...
    
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥20 微信网友居然可以通过vx号找到我绑的手机号
  • ¥15 spring后端vue前端
  • ¥15 寻一个支付宝扫码远程授权登录的软件助手app
  • ¥15 解riccati方程组
  • ¥15 display:none;样式在嵌套结构中的已设置了display样式的元素上不起作用?
  • ¥15 使用rabbitMQ 消息队列作为url源进行多线程爬取时,总有几个url没有处理的问题。
  • ¥15 Ubuntu在安装序列比对软件STAR时出现报错如何解决
  • ¥50 树莓派安卓APK系统签名
  • ¥65 汇编语言除法溢出问题
  • ¥15 Visual Studio问题