简介
在 Go 中连接数据库的方式有很多, 这里我们选择使用 ORM 的方式,
也就不用写原生的 SQL 语句了.
Go 的 ORM 库也有很多, 这里选择了 gorm.
安装 gorm
go get -u github.com/jinzhu/gorm
启动数据库
数据库选择了最主流的 mysql.
创建数据库的方式有很多, 为了便于清理, 选择使用 docker 创建数据库.
新建一个 docker-compose.yml 文件, 在根目录下:
version: "3.7"
services:
mysql:
image: mysql:8
command: --default-authentication-plugin=mysql_native_password
environment:
MYSQL_ROOT_PASSWORD: 1234
ports:
- 3306:3306
adminer:
image: adminer:4
ports:
- 8080:8080
dbclient:
image: mysql:8
command: mysql -hmysql -uroot -p
# source /home/script/db.sql
# select * from tb_users \G;
volumes:
- ./script:/home/script
运行下面的命令在后台启动数据库:
docker-compose up -d mysql
使用下面的命令连接到 msyql 的 cli 上:
docker-compose run --rm dbclient
这会提示你输入密码, 密码是 1234 (在 mysql 的环境变量 MYSQL_ROOT_PASSWORD 中设置).
然后, 在 cli 中输入以下 SQL, 创建一个表格:
CREATE DATABASE IF NOT EXISTS `db_apiserver`;
接下来, 就可以完善 Go 代码了.
初始化数据库连接
在根目录下创建一个 model 文件夹, 这里定义数据模型, 以及数据库的初始连接.
在 model 目录下创建一个 init.go 文件, 用于初始化数据库连接.
package model
import (
"fmt"
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
"github.com/sirupsen/logrus"
"github.com/spf13/viper"
)
type Database struct {
Self *gorm.DB
}
// 单例
var DB *Database
func (db *Database) Init() {
DB = &Database{
Self: GetDB(),
}
}
func (db *Database) Close() {
DB.Self.Close()
}
func openDB(username, password, addr, name string) *gorm.DB {
config := fmt.Sprintf(
"%s:%s@tcp(%s)/%s?charset=utf8mb4&parseTime=%t&loc=%s",
username,
password,
addr,
name,
true,
// "Asia%2FShanghai", // 必须是 url.QueryEscape 的
"Local",
)
db, err := gorm.Open("mysql", config)
if err != nil {
logrus.Fatalf("数据库连接失败. 数据库名字: %s. 错误信息: %s", name, err)
} else {
logrus.Infof("数据库连接成功, 数据库名字: %s", name)
}
setupDB(db)
return db
}
func setupDB(db *gorm.DB) {
db.LogMode(viper.GetBool("gormlog"))
// 用于设置最大打开的连接数,默认值为0表示不限制.设置最大的连接数,可以避免并发太高导致连接mysql出现too many connections的错误。
//db.DB().SetMaxOpenConns(20000)
// 用于设置闲置的连接数.设置闲置的连接数则当开启的一个连接使用完成后可以放在池里等候下一次使用。
db.DB().SetMaxIdleConns(0)
}
func InitDB() *gorm.DB {
return openDB(
viper.GetString("db.username"),
viper.GetString("db.password"),
viper.GetString("db.addr"),
viper.GetString("db.name"),
)
}
func GetDB() *gorm.DB {
return InitDB()
}
注意导入的时候, 需要导入对应的数据库驱动, mysql 需要如下的导入:
"github.com/jinzhu/gorm"
_ "github.com/jinzhu/gorm/dialects/mysql"
主要是定义了一个结构来保存数据库实例 *gorm.DB , 用到了单例模式:
type Database struct {
Self *gorm.DB
}
// 单例
var DB *Database
然后定义了数据库的初始化方法和关闭方法.
打开的时候用到了配置文件中的参数, 需要在配置文件 config.yaml 中添加如下的参数:
db:
name: db_apiserver
addr: 127.0.0.1:3306
username: root
password: "1234"
服务器启动时连接数据库
在 runServer 函数中添加下面的代码:
// 初始化数据库
model.DB.Init()
defer model.DB.Close()
总结
其实连接数据库的问题并不太大, 以前觉得麻烦是因为在本地启动一个数据库麻烦,
但是在有了 docker 之后, 一切就变得简单可重复了, 再也不用担心兼容性了.