Gorm-Open(DB连接与配置)

基于1.31.0

工作原理

graph TD
    A[Open<br/>打开数据库连接] --> B[Initialize Config<br/>初始化配置]
    B --> C[Initialize Dialector<br/>初始化数据库方言]
    C --> D[Setup Connection Pool<br/>设置连接池]
    D --> E[Setup Callbacks<br/>设置回调]
    E --> F[Ping Database<br/>连接数据库测试]
    F --> G[DB Instance Ready<br/>数据库实例就绪]
    
    G --> H[Session<br/>创建会话]
    H --> I[Create New Session<br/>创建新会话]
    I --> J[Apply Session Config<br/>应用会话配置]
    
    G --> K[WithContext<br/>设置上下文]
    K --> L[Set Context<br/>设置上下文]
    
    G --> M[Debug<br/>调试模式]
    M --> N[Set Debug Logger<br/>设置调试日志]
    
    J --> O[Query/Exec Methods<br/>查询/执行方法]
    L --> O
    N --> O
    
    O --> P[AddError<br/>添加错误]
    P --> Q[Error Handling<br/>错误处理]
    
    O --> R[Statement.Build<br/>构建语句]
    R --> S[Generate SQL<br/>生成SQL]
    S --> T[Execute SQL<br/>执行SQL]
    
    T --> U[Return Results<br/>返回结果]
    
    style A fill:#f9f,stroke:#333
    style G fill:#bbf,stroke:#333
    style O fill:#fbf,stroke:#333
    style R fill:#bff,stroke:#333
    style T fill:#bfb,stroke:#333

详细流程

初始化数据库-Open

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
// Open initialize db session based on dialector
// Open 根据 dialector 初始化数据库会话
func Open(dialector Dialector, opts ...Option) (db *DB, err error) {
// 创建一个新的配置实例
config := &Config{}

// 对选项进行排序,确保 Config 类型的选项排在前面
sort.Slice(opts, func(i, j int) bool {
_, isConfig := opts[i].(*Config)
_, isConfig2 := opts[j].(*Config)
return isConfig && !isConfig2
})

// 如果提供了选项,则处理第一个选项
if len(opts) > 0 {
// 如果第一个选项是 Config 类型,则使用它作为配置
if c, ok := opts[0].(*Config); ok {
config = c
} else {
// 否则将默认配置添加到选项列表的开头
opts = append([]Option{config}, opts...)
}
}

// 标记是否跳过初始化后的回调
var skipAfterInitialize bool
// 遍历所有选项并应用它们
for _, opt := range opts {
if opt != nil {
// 应用选项配置
if applyErr := opt.Apply(config); applyErr != nil {
return nil, applyErr
}
// 延迟执行初始化后的回调
defer func(opt Option) {
// 如果标记跳过,则直接返回
if skipAfterInitialize {
return
}
// 执行初始化后的回调
if errr := opt.AfterInitialize(db); errr != nil {
err = errr
}
}(opt)
}
}

// 如果 dialector 实现了 Apply 方法,则应用其配置
if d, ok := dialector.(interface{ Apply(*Config) error }); ok {
if err = d.Apply(config); err != nil {
return
}
}

// 如果未设置命名策略,则使用默认的命名策略
if config.NamingStrategy == nil {
config.NamingStrategy = schema.NamingStrategy{IdentifierMaxLength: 64} // Default Identifier length is 64
}

// 如果未设置日志记录器,则使用默认的日志记录器
if config.Logger == nil {
config.Logger = logger.Default
}

// 如果未设置时间函数,则使用默认的时间函数
if config.NowFunc == nil {
config.NowFunc = func() time.Time { return time.Now().Local() }
}

// 如果提供了 dialector,则设置到配置中
if dialector != nil {
config.Dialector = dialector
}

// 如果未初始化插件映射,则创建一个新的映射
if config.Plugins == nil {
config.Plugins = map[string]Plugin{}
}

// 如果未初始化缓存存储,则创建一个新的 sync.Map
if config.cacheStore == nil {
config.cacheStore = &sync.Map{}
}

// 创建新的 DB 实例
db = &DB{Config: config, clone: 1}

// 初始化回调处理器
db.callbacks = initializeCallbacks(db)

// 如果未初始化子句构建器映射,则创建一个新的映射
if config.ClauseBuilders == nil {
config.ClauseBuilders = map[string]clause.ClauseBuilder{}
}

// 如果提供了 dialector,则初始化数据库连接
if config.Dialector != nil {
err = config.Dialector.Initialize(db)
if err != nil {
// 如果初始化失败,则尝试关闭数据库连接
if db, _ := db.DB(); db != nil {
_ = db.Close()
}

// DB is not initialized, so we skip AfterInitialize
// 数据库未初始化,因此跳过 AfterInitialize 回调
skipAfterInitialize = true
return
}

// 如果启用了错误翻译功能,但 dialector 没有实现 ErrorTranslator 接口,则记录警告
if config.TranslateError {
if _, ok := db.Dialector.(ErrorTranslator); !ok {
config.Logger.Warn(context.Background(), "The TranslateError option is enabled, but the Dialector %s does not implement ErrorTranslator.", db.Dialector.Name())
}
}
}

// 如果启用了预编译语句,则创建预编译语句数据库实例
if config.PrepareStmt {
preparedStmt := NewPreparedStmtDB(db.ConnPool, config.PrepareStmtMaxSize, config.PrepareStmtTTL)
db.cacheStore.Store(preparedStmtDBKey, preparedStmt)
db.ConnPool = preparedStmt
}

// 初始化数据库语句实例
db.Statement = &Statement{
DB: db,
ConnPool: db.ConnPool,
Context: context.Background(),
Clauses: map[string]clause.Clause{},
}

// 如果没有错误且未禁用自动 ping,则尝试 ping 数据库
if err == nil && !config.DisableAutomaticPing {
if pinger, ok := db.ConnPool.(interface{ Ping() error }); ok {
err = pinger.Ping()
}
}

// 如果有错误,则记录错误日志
if err != nil {
config.Logger.Error(context.Background(), "failed to initialize database, got error %v", err)
}

return
}