學習Gorm系列一:創(chuàng)建數(shù)據(jù)庫連接
大家好,我是漁夫子。
所以本系列文章意在深入的學習gorm,以便更好的理解和使用gorm,而不是簡單的使用增、刪、改、查功能。
什么是gorm
gorm是用于golang編程的非常優(yōu)秀的ORM庫,可使開發(fā)者對數(shù)據(jù)庫使用更為方便。該庫不僅支持多種數(shù)據(jù)庫。而且還提供了查詢構(gòu)建器、關(guān)系映射、事務(wù)等多種功能。
初始化數(shù)據(jù)庫連接:gorm.Open
要針對數(shù)據(jù)庫進行操作,第一步就是要創(chuàng)建一個和數(shù)據(jù)庫的連接。在gorm中使用的就是gorm.Open
函數(shù)。接下來就們就看一下gorm.Open都做了些什么事兒。
假設(shè)我們要連接一個mysql數(shù)據(jù)庫,像如下代碼這樣就能建立數(shù)據(jù)的連接:
import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
func main() {
// refer https://github.com/go-sql-driver/mysql#dsn-data-source-name for details
dsn := "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
}
我們看到上面的代碼還依賴了mysql的驅(qū)動庫:gorm.io/driver/mysql
,該庫是mysql的驅(qū)動庫。這個就是要告訴gorm要連接的具體數(shù)據(jù)庫了。在go-gorm項目下還能找到sqlite
、sqlserver
、postgres
以及clickhouse
等常用的數(shù)據(jù)庫的驅(qū)動庫。地址是:https://github.com/go-gorm目錄下。
我們再看下gorm.Open的函數(shù)原型:
func Open(dialector Dialector, opts ...Option) (db *DB, err error)
第一個參數(shù)是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
}
看到這里就明白了,只要具體的數(shù)據(jù)庫驅(qū)動實現(xiàn)了該接口,gorm就能支持該數(shù)據(jù)庫的連接。也就是說上面我們提到的go-gorm目錄下的各種具體的數(shù)據(jù)庫驅(qū)動都實現(xiàn)了Dialector接口。
圖片
dsn是什么
dsn,即data source name,指的是數(shù)據(jù)源名稱。在golang中,其格式如下:
[user[:password]@][net[(addr)]]/dbname[?param1=value1?mN=valueN]
mysql.Open函數(shù)
mysql.Open函數(shù)的返回值是gorm.Dialector對象。也就是說這里只是把相關(guān)的配置賦值給了gorm.Dialector接口類型,并沒有實際的和數(shù)據(jù)庫建立連接。如下是mysql.Open函數(shù)的實現(xiàn):
func Open(dsn string) gorm.Dialector {
dsnConf, _ := mysql.ParseDSN(dsn)
return &Dialector{Config: &Config{DSN: dsn, DSNConfig: dsnConf}}
}
當然,其他數(shù)據(jù)庫的Open函數(shù)也是類似,比如clickhouse數(shù)據(jù)庫的Open函數(shù)實現(xiàn)如下:
func Open(dsn string) gorm.Dialector {
return &Dialector{Config: &Config{DSN: dsn}}
}
建立數(shù)據(jù)庫連接:Dialector.Initialize
在gorm.Open函數(shù)中,是通過Dialector.Initialize函數(shù)和數(shù)據(jù)庫建立實際連接的。如下:
if config.Dialector != nil {
err = config.Dialector.Initialize(db)
}
Dialector就是上文中提到的通過各個具體的數(shù)據(jù)庫驅(qū)動的Open函數(shù)返回的接口類型。實際上也就是自己驅(qū)動下Dialector對象。然后在執(zhí)行各自實例的Initialize函數(shù),就能通過dsn中配置的地址和賬號建立數(shù)據(jù)庫連接了。
圖片
我們還是以mysql數(shù)據(jù)庫為例,我們看下Initialize函數(shù)的核心實現(xiàn):
圖片
本質(zhì)上,在創(chuàng)建數(shù)據(jù)庫連接的時候還是基于golang標準庫的database/sql庫實現(xiàn)的。最終,通過gorm.Open函數(shù)就初始化了一個數(shù)據(jù)庫的連接
核心數(shù)據(jù)結(jié)構(gòu)
上文提到,通過gorm.Open函數(shù)會得到一個gorm.DB對象。該對象是gorm中的核心數(shù)據(jù)結(jié)構(gòu)。如下是gorm.DB的結(jié)構(gòu)體:
圖片
在gorm.DB結(jié)構(gòu)中主要包含兩個類型的字段:Config和Statement。Config結(jié)構(gòu)體根據(jù)名字可知主要是一些和數(shù)據(jù)庫相關(guān)的配置,比如和賬號密碼以及連接地址相關(guān)的Dailector、數(shù)據(jù)庫的連接ConnPool,日志相關(guān)的等。
Statement結(jié)構(gòu)體,我們看到該結(jié)構(gòu)體的主要由Table、Model、Select、Schema等組成,可想而知是跟具體的sql語句有關(guān)系的。
總結(jié)
通過gorm建立數(shù)據(jù)庫連接的時候,要依賴于具體連接哪種數(shù)據(jù)庫,所以gorm項目下提供了多種數(shù)據(jù)庫的驅(qū)動。這些數(shù)據(jù)庫驅(qū)動遵守gorm提供的接口類型Dailector來創(chuàng)建連接。實際創(chuàng)建連接的函數(shù)是Initialize函數(shù),并將創(chuàng)建好的連接返回給gorm.DB.ConnPool字段中。