与包共享数据库连接

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

Share database connection with packages

问题

我是你的中文翻译助手,以下是翻译好的内容:

我是新手使用golang。我试图在我的包中共享mysql数据库连接,以后可能在几个包中共享。为了避免在每个包中定义数据库连接,我创建了一个名为Database的包,现在我正在尝试获取该包,连接到数据库并在整个包中使用该对象。

我正在使用这个mysql插件:github.com/go-sql-driver/mysql

以下是我的代码:

main.go

package main

import (
	"log"
    "./packages/db" // 这是我的自定义数据库包
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

var dbType Database.DatabaseType
var db *sql.DB

func main() {
	log.Printf("-- 进入 main 函数...")
	dbType := Database.New()
	db = dbType.GetDb()

	dbType.DbConnect()
	
	delete_test_data()

	dbType.DbClose()
}

func delete_test_data(){
	log.Printf("-- 进入 delete_test_data 函数...")

	//db.Exec("DELETE FROM test;")
}

packages/db/db.go

package Database

import (
    "log"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

type DatabaseType struct {
   DatabaseObject *sql.DB
}

func New()(d *DatabaseType) {
    d = new(DatabaseType)
    //db.DatabaseObject = db.DbConnect()
    return d
}


func (d *DatabaseType) DbConnect() *DatabaseType{
    log.Printf("-- 进入 DbConnect 函数...")
    var err error

    if d.DatabaseObject == nil {
        log.Printf("--------- > 数据库为空...")
        d.DatabaseObject, err = sql.Open("mysql", "...")
        if err != nil {
            panic(err.Error())
        }

        err = d.DatabaseObject.Ping()
        if err != nil {
            panic(err.Error())
        }
    }

    return d
}

func (d *DatabaseType) DbClose(){
    log.Printf("-- 进入 DbClose 函数...")
    defer d.DatabaseObject.Close()
}

func (d *DatabaseType) GetDb() *sql.DB{
   return d.DatabaseObject
}

一切都正常,没有错误,直到我取消注释这一行:

db.Exec("DELETE FROM test;")

有人可以告诉我共享数据库连接的正确方法吗?

英文:

I'm new with golang. I'm trying to share mysql database connection in my package, latter maybe in several packages. To skip defining database connection in every package I've created Database package and now I'm trying to get that package, connect to db and use that object in whole package.

I'm using this mysql plugin: github.com/go-sql-driver/mysql

here is my code:

main.go

package main

import (
	"log"
    "./packages/db" // this is my custom database package
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

var dbType Database.DatabaseType
var db *sql.DB

func main() {
	log.Printf("-- entering main...")
	dbType := Database.New()
	db = dbType.GetDb()

	dbType.DbConnect()
	
	delete_test_data()

	dbType.DbClose()
}

func delete_test_data(){
	log.Printf("-- entering delete_test_data...")

	//db.Exec("DELETE FROM test;")
}

packages/db/db.go

package Database

import (
    "log"
    "database/sql"
    _ "github.com/go-sql-driver/mysql"
)

type DatabaseType struct {
   DatabaseObject *sql.DB
}

func New()(d *DatabaseType) {
    d = new(DatabaseType)
    //db.DatabaseObject = db.DbConnect()
    return d
}


func (d *DatabaseType) DbConnect() *DatabaseType{
    log.Printf("-- entering DbConnect...")
    var err error

    if d.DatabaseObject == nil {
        log.Printf("--------- > Database IS NIL...")
        d.DatabaseObject, err = sql.Open("mysql", "...")
        if err != nil {
            panic(err.Error())
        }

        err = d.DatabaseObject.Ping()
        if err != nil {
            panic(err.Error())
        }
    }

    return d
}

func (d *DatabaseType) DbClose(){
    log.Printf("-- entering DbClose...")
    defer d.DatabaseObject.Close()
}

func (d *DatabaseType) GetDb() *sql.DB{
   return d.DatabaseObject
}

Everything is ok and without error until I uncomment this line:

db.Exec("DELETE FROM test;")

Can someone tell me what is correct way to share db connection?

答案1

得分: 1

你的dbType.DbConnect()方法返回一个已初始化连接的DatabaseType,但你完全忽略了返回值。

此外,为了简化你的代码,可以考虑使用New(host string) *DB代替三个不同的函数(New/DbConnect/GetDb),它们都做同样的事情。

例如:

package datastore

type DB struct {
    // 直接嵌入这个
    *sql.DB
}

func NewDB(host string) (*DB, error) {
    db, err := sql.Open(...)
    if err != nil {
        return nil, err
    }
    
    return &DB{db}, nil
}
package main

var db *datastore.DB

func main() {
    var err error
    db, err = datastore.NewDB(host)
    if err != nil {
        log.Fatal(err)
    }
    
    err := someFunc()
}

func someFunc() error {
    rows, err := db.Exec("DELETE FROM ...")
    // 处理错误,解析结果等等
}

这样可以减少你需要做的操作,并且你仍然可以调用DB类型的Close()方法,因为它嵌入了*sql.DB,不需要实现自己的Close()方法。

英文:

Your dbType.DbConnect() method returns a DatabaseType with an initialized connection, but you're ignoring the return value entirely.

Further - to simplify your code - look at having New(host string) *DB instead of three different functions (New/DbConnect/GetDb) that do the same thing.

e.g.

package datastore

type DB struct {
    // Directly embed this
    *sql.DB
}

func NewDB(host string) (*DB, error) {
    db, err := sql.Open(...)
    if err != nil {
        return nil, err
    }
    
    return &DB{db}, nil
}

package main

var db *datastore.DB

func main() {
    var err error
    db, err = datastore.NewDB(host)
    if err != nil {
        log.Fatal(err)
    }
    
    err := someFunc()
}

func someFunc() error {
    rows, err := db.Exec("DELETE FROM ...")
    // Handle the error, parse the result, etc.
}

This reduces the juggling you have to do, and you can still call close on your DB type because it embeds *sql.DB - there's no need to implement your own Close() method.

huangapple
  • 本文由 发表于 2015年10月3日 20:29:40
  • 转载请务必保留本文链接:https://go.coder-hub.com/32922572.html
匿名

发表评论

匿名网友

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

确定