1 前言
gorm源码地址: Gorm , 本文基于commit:cef3de694d9615c574e82dfa0b50fc7ea2816f3e
官方入门指南: Doc
2 连接数据库代码示例
目前Gorm官方支持的数据库类型有:MySQL, PostgreSQL, SQLite, SQL Server.
目前Go官方支持MySQL驱动
下面来看连接MySQL的数据库的基本代码
package main |
|
import ( |
|
"fmt" |
|
"time" |
|
"gorm.io/driver/mysql" |
|
"gorm.io/gorm" |
|
) |
|
func main() { |
|
// 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情 |
|
dsn := fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?timeout=%s&readTimeout=%s&writeTimeout=%s", |
|
"root", "zbwmysql", "127.0.0.1", "3306", "user_db", "100ms", "2s", "3s") |
|
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{}) |
|
if err != nil { |
|
fmt.Printf("gorm open fail, err:%v dsn:%v/n", err, dsn) |
|
} |
|
mysqlDB, err := db.DB() |
|
if err != nil { |
|
fmt.Printf("get mysql db fail, err:%v/n", err) |
|
} |
|
// 参考 https://github.com/go-sql-driver/mysql#important-settings 获取详情 |
|
mysqlDB.SetConnMaxLifetime(time.Minute * 3) // 客户端将空闲连接主动断开的超时时间,官方建议小于5分钟 |
|
mysqlDB.SetMaxOpenConns(10) // 取决于服务器的配置 |
|
mysqlDB.SetMaxIdleConns(10) // 官方建议和SetMaxOpenConns相同 |
|
} |
这里有必要看下 timeout
,readTimeout
,writeTimeout
,SetConnMaxLifetime
三个参数
timeout
是指 建立连接的一个超时时间
readTimeout
是指 I/O 读操作的超时时间
writeTimeout
是指 I/O 写操作的超时时间
SetConnMaxLifetime
是指客户端将空闲连接主动断开的超时时间,
如果设置为0,则连接池的连接将这一直被复用,但是系统会主动将长时间的连接杀掉,
因此若客户端再次使用长时间空闲的连接将会报错,driver: bad connection
问题的修复记录,可以看 issues-1120
3 连接数据库代码分析
从上一节看,Gorm连接数据库的过程只需要调用一个函数,
func Open(dialector Dialector, opts ...Option) (db *DB, err error)
但是Gorm目前是MySQL, PostgreSQL, SQLite, SQL Server,四种类型的数据库的,这个是怎么做到的呢?
这就需要具体看下请求参数Dialector
和 返回参数DB
及Open
函数内部实现
首先让我们先看看Golang的interface
类型
3.1 interface
理解
An interface type is defined as a set of method signatures.
A value of interface type can hold any value that implements those methods.
A type implements an interface by implementing its methods. There is no explicit declaration of intent, no "implements" keyword.
以上摘抄自A Tour of Go , interface是一种包含方法定义的类型,通过实现该interface的所有方法来隐式实现该接口。
3.2 Dialector接口定义
Dialector定义如下,这里对部分方法加了注释,方便理解。
// Dialector GORM database dialector |
|
type Dialector interface { |
|
Name() string // 驱动名称 |
|
Initialize(*DB) error // 初始化连接 |
|
Migrator(db *DB) Migrator |
|
DataTypeOf(*schema.Field) string // 类型映射 |
|
DefaultValueOf(*schema.Field) clause.Expression // 类型默认值 |
|
BindVarTo(writer clause.Writer, stmt *Statement, v interface{}) |
|
QuoteTo(clause.Writer, string) |
|
Explain(sql string, vars ...interface{}) string // SQL语句格式化输出 |
|
} |
不仅仅Mysql驱动,PostgreSQL, SQLite, SQL Server驱动都得实现Dialector
中定义的全部方法。
并且这些方法恰恰是不同数据库的区别所在,比如不同数据库的数据类型是有差异的,即使含义相同,写法也可能不同,
因此gorm的数据类型映射到不同数据库能识别的类型,这就是DataTypeOf
实现的功能。
可以在go-gorm找到各种数据库的Dialector实现,如PostgreSQL Dialector,MySQL Dialector
3.3 DB
结构体定义
DB
定义如下,这里对部分方法加了注释,方便理解。
// DB GORM DB definition |
|
type DB struct { |
|
*Config // 连接及其连接相关信息等 |
|
Error error |
|
RowsAffected int64 |
|
Statement *Statement // SQL语句执行相关信息 |
|
clone int |
|
} |
其中,Config中会保留连接ConnPool 、CRUD相关的函数callbacks等信息,部分代码代码如下,完整代码见gorm.Config
// Config GORM config |
|
type Config struct { |
|
// ClauseBuilders clause builder |
|
ClauseBuilders map[string]clause.ClauseBuilder |
|
// ConnPool db conn pool |
|
ConnPool ConnPool |
|
// Dialector database dialector |
|
Dialector |
|
// Plugins registered plugins |
|
Plugins map[string]Plugin |
|
callbacks *callbacks |
|
cacheStore *sync.Map |
|
} |
看了Open
函数的请求参数和返回参数,接下来我们看看内部的具体实现
本站声明:
1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。
原创文章,作者:ItWorker,如若转载,请注明出处:https://blog.ytso.com/tech/database/293375.html