Gorm框架 连接数据库

Gorm 支持多种数据库,包括互联网应用通常使用的 Mysql 数据库。连接 Mysql 主要有两个步骤:

  • 配置 DSN (Data Source Name);
  • 使用 gorm.Open 连接数据库。

 

1. 配置 DSN (Data Source Name)

Gorm 使用 dsn 作为连接数据库的参数,dsn 翻译过来就叫数据源名称,用来描述数据库连接信息。一般都包含数据库连接地址,账号,密码之类的信息。

DSN 格式:

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]

Mysql 连接 dsn 范例:

// Mysql dsn格式
// 涉及参数:
// username   数据库账号
// password   数据库密码
// host       数据库连接地址,可以是Ip或者域名
// port       数据库端口
// Dbname     数据库名
username:password@tcp(host:port)/Dbname?charset=utf8&parseTime=True&loc=Local

// 填上参数后的例子
// username = root
// password = 123456
// host     = localhost
// port     = 3306
// Dbname   = tizi365
// 后面K/V键值对参数含义为:
//  charset=utf8 客户端字符集为 utf8
//  parseTime=true 支持把数据库 datetime 和 date 类型转换为 golang 的 time.Time 类型
//  loc=Local 使用系统本地时区
root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local

// gorm 设置mysql连接超时参数
// 开发的时候经常需要设置数据库连接超时参数,gorm 是通过 dsn 的 timeout 参数配置
// 例如,设置 10 秒后连接超时,timeout=10s
//下面是完成的例子
root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local&timeout=10s

// 设置读写超时时间
// readTimeout - 读超时时间,0代表不限制
// writeTimeout - 写超时时间,0代表不限制
root:123456@tcp(localhost:3306)/tizi365?charset=utf8&parseTime=True&loc=Local&timeout=10s&readTimeout=30s&writeTimeout=60s

 

2. 使用 gorm.Open 连接数据库

有了上面配置的 dsn 参数,就可以使用 gorm.Open 方法连接数据库。

下面是连接数据库的范例:

package main

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main()  {
    // 配置 MySQL 连接参数
	username := "root"  // 账号
	password := "123456" // 密码
	host := "127.0.0.1" // 数据库地址,可以是Ip或者域名
	port := 3306 // 数据库端口
	Dbname := "tizi365" // 数据库名
	timeout := "10s" // 连接超时,10秒
	
	// 拼接下 dsn 参数, dsn 格式可以参考上面的语法,这里使用 Sprintf 动态拼接 dsn 参数,因为一般数据库连接参数,我们都是保存在配置文件里面,需要从配置文件加载参数,然后拼接 dsn。
	dsn := fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8&parseTime=True&loc=Local&timeout=%s", username, password, host, port, Dbname, timeout)

	// 连接 Mysql, 获得 DB 类型实例,用于后面的数据库读写操作。
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}

	// 延时关闭数据库连接
	defer db.Close()
}

 

3. gorm 调试模式

在程序在开始阶段,为了方便对代码进行调试,需要了解 Gorm 操作到底执行什么 Sql 语句,我们可以打开调试日志,这样gorm 会打印出执行的每一条 Sql 语句。

使用 Debug 函数执行查询的范例:

result := db.Debug().Where("username = ?", "tizi365").First(&u)

 

4. gorm 数据库连接池

在高并发实践中,为了提高数据库连接的使用率,避免重复建立数据库连接带来的性能消耗,会经常使用数据库连接池技术来维护数据库连接。Gorm 自带了数据库连接池使用非常简单只要设置下数据库连接池参数即可。

数据库连接池使用范例:

// 定义一个工具包,用来管理gorm数据库连接池的初始化工作。
package tools

// 定义全局的db对象,我们执行数据库操作主要通过他实现。
var _db *gorm.DB

// 包初始化函数,golang 特性,每个包初始化的时候会自动执行 init 函数,这里用来初始化 gorm。
func init() {
    // ...忽略dsn配置,请参考上面例子...
    
    // 声明 err 变量,下面不能使用 := 赋值运算符,否则_db变量会当成局部变量,导致外部无法访问 _db 变量
    var err error
    // 连接 Mysql, 获得DB类型实例,用于后面的数据库读写操作。
    _db, err = gorm.Open(mysql.Open(dsn), &gorm.Config{})
    if err != nil {
		panic("连接数据库失败, error=" + err.Error())
	}
     
    sqlDB, _ := db.DB()

    // 设置数据库连接池参数
    sqlDB.SetMaxOpenConns(100)   // 设置数据库连接池最大连接数
    sqlDB.SetMaxIdleConns(20)   // 连接池最大允许的空闲连接数,如果没有sql任务需要执行的连接数大于20,超过的连接会被连接池关闭。
}

// 获取 gorm db 对象,其他包需要执行数据库查询的时候,只要通过 tools.getDB() 获取 db 对象即可。
// 不用担心协程并发使用同样的db对象会共用同一个连接,db 对象在调用他的方法的时候会从数据库连接池中获取新的连接
func GetDB() *gorm.DB {
	return _db
}

使用范例:

package main
// 导入tools包
import tools

func main() {
    // 获取 DB
    db := tools.GetDB()
    
    // 执行数据库查询操作
    u := User{}
	// 自动生成sql: SELECT * FROM `users`  WHERE (username = 'tizi365') LIMIT 1
	db.Where("username = ?", "tizi365").First(&u)
}

注意:使用连接池技术后,千万不要使用完 db 后调用 db.Close 关闭数据库连接,这样会导致整个数据库连接池关闭,导致连接池没有可用的连接。

Gorm 新增记录:定义一个用户,并初始化数据,插入一条用户数据,执行 db.Create(&u)。Gorm 如何获取新插入记录的自增 ID:Gorm 2.0 版本以后,默认会自动返回主键 ID 值。