与软件包共享数据库连接

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?

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.