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