在Go Postgres中连接到多个数据库的最佳方法

I'm developing a website builder and store each website data in separate databases.
My question is how to handle multiple database connection properly and efficiently. All databases and code are in same server

I have create my own way to connect to multiple connection database.

first I create the base file for postgre :

type PostgreHost struct {
    Driver   string
    Database string
    Username string
    Ssl      string
    Password string
}

type PostgreSystem interface {
    Init()
    Connect() (*sqlx.DB, error)
}

var logger *log.Logger

func (p PostgreHost) Init() {
    logger = log.New(os.Stderr,
        "Postgre",
        log.Ldate|log.Ltime|log.Lshortfile)
}

func (p *PostgreHost) Connect() (*sqlx.DB, error) {
    connection := fmt.Sprintf("user=%v password= %v dbname=%v sslmode=%v", p.Username, p.Password, p.Database, p.Ssl)
    db, err := sqlx.Connect(
        p.Driver,
        connection)
    if err != nil {
        logger.Fatal(err)
        return nil, err
    }

    return db, nil
}

func GetPostgreDb(postgre PostgreSystem) (*sqlx.DB, error) {
    return postgre.Connect()
}

and then call it to create list of the connection like this :

//we create different types of databse connection here
func SystemConnection() map[string]interface{} {
    listConnection := make(map[string]interface{})
    var err error
    // create redis connection
    redisConn := RedisHost{
        Address:  "localhost:6379",
        Password: "",
        DB:       0,
    }

    redisConnection, err := redisConn.Connect()
    if err != nil {
        panic(err)
    }

    // create postgre connection
    postgreConn := PostgreHost{
        Driver:   "postgres",
        Database: "postgres",
        Username: "postgres",
        Ssl:      "disable",
        Password: "root",
    }
   // you can create your another connection here : 
   postgreConn2 := PostgreHost{
        Driver:   "postgres",
        Database: "postgres",
        Username: "postgres",
        Ssl:      "disable",
        Password: "root",
    }

    postgreConnection, err := GetPostgreDb(&postgreConn)

    if err != nil {
        panic(err)
    }

    postgreConnection2, err := GetPostgreDb(&postgreConn2)

    if err != nil {
        panic(err)
    }

    listConnection["redis"] = redisConnection
    listConnection["postgre"] = postgreConnection
    listConnection["postgre2"] = postgreConnection2
    return listConnection
}

and finally call all the connection from the map :

    //getting list of all the connection.
    listConnection := database.SystemConnection()

    //getting redis connection convert it from interface to *redisClient.
    redisConn := listConnection["redis"].(*redis.Client)

    // get postgre connection.
    postgreConn := listConnection["postgre"].(*sqlx.DB)
    postgreConn2 := listConnection["postgre2"].(*sqlx.DB)

you can get all the source code from here. it still on progress but hopefully you can get the idea. Hope it helps.

  • Have a context struct to represent a site
  • This context struct holds a DB connection
  • When a user logged in, also set which site is active for him / her (I assume that a user account can have more than one sites).
  • When the user accesses the server, check the cookie for the site
  • Carefully use mutex to get the context from global list / map (map would be map[string]Context) based on the site name obtained from the cookie.
  • If the context doesn't exist, instantiate one. Internally, it creates a connection to the DB to the appropriate table for the site and registers itself to the global list (use mutex).
  • In each context instance, have a timer for certain minutes which resets when accessed. When it timed out (i.e., when it's not accessed for certain minutes), or the last user who owns the site logged out, it will remove itself from global list (again, use mutex) and drop its DB connection.