连接数据库
GORM
官方支持的数据库类型有:MySQL
、PostgreSQL
、SQlite
、SQL Server
连接Mysql
数据库
项目初始化
shell
go mod init gorm-related
- 项目目录
shell
.
├── config
│ └── db.yaml # 配置文件
├── go.mod
├── go.sum
└── main.go // 入口文件
- 配置文件:
config/db.yaml
yaml
mysql:
db1:
username: root
password: study_student
host: 127.0.0.1
port: 1000
dbName: lyb
下载依赖
shell
# 连接数据库使用
go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql
# 读取mysql yaml配置
go get -u github.com/spf13/viper
连接数据库
- 拆分为下面三步:
读取yaml
的mysql
配置
Go
type DatabaseConfig struct {
Username string
Password string
Host string
Port int
DBName string
}
// 获取数据库配置
func loadDbConfig(configFile string) (*DatabaseConfig, error) {
viper.SetConfigFile(configFile)
err := viper.ReadInConfig()
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
var config DatabaseConfig
err = viper.UnmarshalKey("mysql.db1", &config)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}
return &config, nil
}
根据配置生成连接DSN(Data Source Name)
Data Source Name 格式如下
Go
[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...¶mN=valueN]
Data Source Name 一些例子
TIP
要支持完整的
UTF-8
编码,需要将charset=utf8
更改为charset=utf8mb4
parseTime=true
支持把数据库datetime
和date
类型转换为golang
的time.Time
类型loc=Local
使用系统本地时区timeout
数据库连接超时时间,例如timeout=10s
readTimeout
读超时时间,0代表不限制
writeTimeout
写超时时间,0代表不限制
Go
//mysql dsn格式
//涉及参数:
//username 数据库账号
//password 数据库密码
//host 数据库连接地址,可以是Ip或者域名
//port 数据库端口
//Dbname 数据库名
username:password@tcp(host:port)/Dbname?charset=utf8mb4&parseTime=True&loc=Local
//填上参数后的例子
//username = admin
//password = 258369
//host = 127.0.0.1
//port = 1000
//Dbname = gorm
//后面K/V键值对参数含义为:
// charset=utf8mb4 客户端字符集为utf8mb4(要支持完整的UTF-8编码,需要将charset=utf8更改为charset=utf8mb4
// parseTime=true 支持把数据库datetime和date类型转换为golang的time.Time类型
// loc=Local 使用系统本地时区
admin:258369@tcp(127.0.0.1:1000)/gorm?charset=utf8mb4&parseTime=True&loc=Local
//gorm 设置mysql连接超时参数
//开发的时候经常需要设置数据库连接超时参数,gorm是通过dsn的timeout参数配置
//例如,设置10秒后连接超时,timeout=10s
//下面是完成的例子
admin:258369@tcp(127.0.0.1:1000)/gorm?charset=utf8mb4&parseTime=True&loc=Local&timeout=10s
//设置读写超时时间
// readTimeout - 读超时时间,0代表不限制
// writeTimeout - 写超时时间,0代表不限制
admin:258369@tcp(127.0.0.1:1000)/gorm?charset=utf8mb4&parseTime=True&loc=Local&timeout=10s&readTimeout=30s&writeTimeout=60s
代码
Go
// 生成连接数据库链接
func genDbUrl(config *DatabaseConfig) string {
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", config.Username, config.Password, config.Host, config.Port, config.DBName)
}
连接数据库
Go
// 连接数据库
func connectToDb(dbUrl string) (*gorm.DB, error) {
db, err := gorm.Open(mysql.Open(dbUrl), &gorm.Config{})
if err != nil {
return nil, fmt.Errorf("failed to connect to MySQL database: %w", err)
}
return db, nil
}
- 完整代码
Go
package main
import (
"fmt"
"log"
"github.com/spf13/viper"
"gorm.io/driver/mysql"
"gorm.io/gorm"
)
type DatabaseConfig struct {
Username string
Password string
Host string
Port int
DBName string
}
// 获取数据库配置
func loadDbConfig(configFile string) (*DatabaseConfig, error) {
viper.SetConfigFile(configFile)
err := viper.ReadInConfig()
if err != nil {
return nil, fmt.Errorf("failed to read config file: %w", err)
}
var config DatabaseConfig
err = viper.UnmarshalKey("mysql.db1", &config)
if err != nil {
return nil, fmt.Errorf("failed to unmarshal config: %w", err)
}
return &config, nil
}
// 生成连接数据库链接
func genDbUrl(config *DatabaseConfig) string {
return fmt.Sprintf("%s:%s@tcp(%s:%d)/%s?charset=utf8mb4&parseTime=True&loc=Local", config.Username, config.Password, config.Host, config.Port, config.DBName)
}
// 连接数据库
func connectToDb(dbUrl string) (*gorm.DB, error) {
db, err := gorm.Open(mysql.Open(dbUrl), &gorm.Config{})
if err != nil {
return nil, fmt.Errorf("failed to connect to MySQL database: %w", err)
}
return db, nil
}
func main() {
// 获取数据库配置
dbConfig, err := loadDbConfig("config/db.yaml")
if err != nil {
log.Fatalf("Failed to load config: %v", err)
}
// 根据数据库配置获取url
dbUrl := genDbUrl(dbConfig)
// 根据生产的url连接数据库
db, connectErr := connectToDb(dbUrl)
if connectErr != nil {
log.Fatalf("Failed to connect to MySQL database: %v", connectErr)
}
fmt.Println("Successfully connected to MySQL database!", db)
}
高级配置
日志配置
日志级别有
Silent
、Error
、Warn
、Info
Gorm
有一个默认 logger实现,默认情况下,它会打印慢SQL
和错误
可以在
初始化
时自定义它,会改变全局日志规则
Go
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer
logger.Config{
SlowThreshold: time.Second, // Slow SQL threshold 慢sql阀值
LogLevel: logger.Info, // Log level 日志级别
IgnoreRecordNotFoundError: true, // Ignore ErrRecordNotFound error for logger 忽略ErrRecordNotFound(记录未找到)错误
ParameterizedQueries: true, // Don't include params in the SQL log 不要在 SQL 日志中包含参数
Colorful: false, // Disable color 关闭颜色
},
)
db, err := gorm.Open(mysql.Open(dbUrl), &gorm.Config{
Logger: newLogger
})
- 修改一个连续会话日志
Go
// Continuous session mode
tx := db.Session(&Session{Logger: newLogger})
tx.First(&user)
tx.Model(&user).Update("Age", 18)
Debug
单个操作,将当前操作
的log
级别调整为logger.Info
Go
DB.Debug().AutoMigrate(&User{})
Debug
方法原理如下
Go
// Debug start debug mode
func (db *DB) Debug() (tx *DB) {
tx = db.getInstance()
return tx.Session(&Session{
Logger: db.Logger.LogMode(logger.Info),
})
}