golang 数据库连接池

简介

本文介绍如何使用gorm 2 连接池的使用代码例子,该连接池支持Mysql、postgres、sqlite三种数据库。

本篇文章代码本来是从一个工程里面摘取出来的一些代码片段, 不能直接运行。后来因为有同学提问,所以特意把相关代码提取出来,给读者提供一些直接运行的代码。

初始化文件夹

mkdir hello 
cd hello 
go mod init example.com/hello 

安装依赖

go get gorm.io/gorm
go get gorm.io/driver/mysql
go get gorm.io/driver/postgres
go get gorm.io/driver/sqlite

编写代码

  • 配置文件config.json
{
  "database": {
    "name": "db1",
    "password": "123456",
    "user": "root",
    "type": "mysql",
    "host": "127.0.0.1",
    "port": "3306",
    "table_prefix": ""
  }
}

根据实际情况读者可以自己填写自己的数据库信息

  • 读取配置文件代码config/config.go
package config

import (
"encoding/json"
"os"
)

// Config 配置对象
type Config struct {
    Database *Database `json:"database"`
}

// GlobalConfigSetting 配置实例
var GlobalConfigSetting = &Config{}

// Setup 配置
func Setup() {
    filePtr, err := os.Open("config.json") //config的文件目录
    if err != nil {
        return
    }
    defer filePtr.Close()
    // 创建json解码器
    decoder := json.NewDecoder(filePtr)
    err = decoder.Decode(GlobalConfigSetting)
    DatabaseSetting = GlobalConfigSetting.Database

}

// Database 数据库配置对象
type Database struct {
    Type        string `json:"type"`
    User        string `json:"user"`
    Password    string `json:"password"`
    Host        string `json:"host"`
    Port        string `json:"port"`
    Name        string `json:"name"`
    TablePrefix string `json:"table_prefix"`
}

// DatabaseSetting 数据库配置对象 实例
var DatabaseSetting = &Database{}


连接池代码dao/dao.go


package dao

import (
    "example.com/hello/config"
    "fmt"
    "log"
    "time"

    "gorm.io/driver/mysql"
    "gorm.io/driver/postgres"
    "gorm.io/driver/sqlite"
    "gorm.io/gorm"
)

// db连接
var db *gorm.DB

// Setup 初始化连接
func Setup() {
    // db = newConnection()
    var dbURI string
    var dialector gorm.Dialector
    if config.DatabaseSetting.Type == "mysql" {
        dbURI = fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8&parseTime=true",
            config.DatabaseSetting.User,
            config.DatabaseSetting.Password,
            config.DatabaseSetting.Host,
            config.DatabaseSetting.Port,
            config.DatabaseSetting.Name)
        dialector = mysql.New(mysql.Config{
            DSN:                       dbURI, // data source name
            DefaultStringSize:         256,   // default size for string fields
            DisableDatetimePrecision:  true,  // disable datetime precision, which not supported before MySQL 5.6
            DontSupportRenameIndex:    true,  // drop & create when rename index, rename index not supported before MySQL 5.7, MariaDB
            DontSupportRenameColumn:   true,  // `change` when rename column, rename column not supported before MySQL 8, MariaDB
            SkipInitializeWithVersion: false, // auto configure based on currently MySQL version
        })
    } else if config.DatabaseSetting.Type == "postgres" {
        dbURI = fmt.Sprintf("host=%s port=%s user=%s dbname=%s sslmode=disable password=%s",
            config.DatabaseSetting.Host,
            config.DatabaseSetting.Port,
            config.DatabaseSetting.User,
            config.DatabaseSetting.Name,
            config.DatabaseSetting.Password)
        dialector = postgres.New(postgres.Config{
            DSN:                  "user=gorm password=gorm dbname=gorm port=9920 sslmode=disable TimeZone=Asia/Shanghai",
            PreferSimpleProtocol: true, // disables implicit prepared statement usage
        })
    } else { // sqlite3
        dbURI = fmt.Sprintf("test.db")
        dialector = sqlite.Open("test.db")
    }
    conn, err := gorm.Open(dialector, &gorm.Config{})
    if err != nil {
        log.Print(err.Error())
    }
    sqlDB, err := conn.DB()
    if err != nil {
        log.Print("connect db server failed.")
    }
    sqlDB.SetMaxIdleConns(10)                   // SetMaxIdleConns sets the maximum number of connections in the idle connection pool.
    sqlDB.SetMaxOpenConns(100)                  // SetMaxOpenConns sets the maximum number of open connections to the database.
    sqlDB.SetConnMaxLifetime(time.Second * 600) // SetConnMaxLifetime sets the maximum amount of time a connection may be reused.
    db = conn
}

// GetDB 开放给外部获得db连接
func GetDB() *gorm.DB {
    sqlDB, err := db.DB()
    if err != nil {
        fmt.Errorf("connect db server failed.")
        Setup()
    }
    if err := sqlDB.Ping(); err != nil {
        sqlDB.Close()
        Setup()
    }

    return db
}


  • 连接池调用 main.go
package main

import (
    "example.com/hello/config"
    "example.com/hello/dao"
    "fmt"
    "gorm.io/gorm"
)

// Product 产品
type Product struct {
    gorm.Model
    Code  string
    Price uint
}

func SetupModel()  {
    db := dao.GetDB()
    // 自动迁移模式
    db.AutoMigrate(&Product{})
    // 创建
    db.Create(&Product{Code: "L1212", Price: 1000})
}

func main() {
    config.Setup()
    dao.Setup()
    fmt.Println("hello")
    SetupModel()
}

  • 完整的go.mod函数
module example.com/hello

go 1.17

require (
    gorm.io/driver/mysql v1.2.3
    gorm.io/driver/postgres v1.2.3
    gorm.io/driver/sqlite v1.2.6
    gorm.io/gorm v1.22.5
)

require (
    github.com/go-sql-driver/mysql v1.6.0 // indirect
    github.com/jackc/chunkreader/v2 v2.0.1 // indirect
    github.com/jackc/pgconn v1.10.1 // indirect
    github.com/jackc/pgio v1.0.0 // indirect
    github.com/jackc/pgpassfile v1.0.0 // indirect
    github.com/jackc/pgproto3/v2 v2.2.0 // indirect
    github.com/jackc/pgservicefile v0.0.0-20200714003250-2b9c44734f2b // indirect
    github.com/jackc/pgtype v1.9.0 // indirect
    github.com/jackc/pgx/v4 v4.14.0 // indirect
    github.com/jinzhu/inflection v1.0.0 // indirect
    github.com/jinzhu/now v1.1.4 // indirect
    github.com/mattn/go-sqlite3 v1.14.9 // indirect
    golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 // indirect
    golang.org/x/text v0.3.7 // indirect
)

执行程序


go mod tidy 
# 执行后看到数据库内products表会自动创建一条记录
go run main.go 

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,233评论 4 360
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,013评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,030评论 0 241
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,827评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,221评论 3 286
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,542评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,814评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,513评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,225评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,497评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 31,998评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,342评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 32,986评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,055评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,812评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,560评论 2 271
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,461评论 2 266