模型定义
Userusersgorm
sql

1 模型定义商品表

CREATE TABLE `goods` (
	`id` INT (10) UNSIGNED NOT NULL AUTO_INCREMENT COMMENT '自增ID,商品Id',
	`name` VARCHAR (30) NOT NULL COMMENT '商品名',
	`price` DECIMAL (10, 2) UNSIGNED NOT NULL COMMENT '商品价格',
	`type_id` INT (10) UNSIGNED NOT NULL COMMENT '商品类型Id',
	`createtime` INT (10) NOT NULL DEFAULT 0 COMMENT '创建时间',
	PRIMARY KEY (`id`)
) ENGINE = INNODB DEFAULT CHARSET = utf8mb4

将上述表翻译为模型后,如下:

type Good struct {
	Id         int  //表字段名为:id
	Name       string //表字段名为:name
	Price      float64 //表字段名为:price
	TypeId     int  //表字段名为:type_id
	CreateTime int64 `gorm:"column:createtime"`  //表字段名为:createtime
}

默认 gorm 对 struct 字段名使用 Snake Case 命名风格转换成 mysql 表字段名(需要转换成小写字母)。

Snake Case 命名风格,就是各个单词之间用下划线(_)分隔,例如: CreateTime的Snake Case风格命名为 create_time。

ID

2 模型标签

标签定义:

`gorm:"标签内容"`
;

gorm 常用标签如下:

gorm:"column:createtime" gorm:"column:id; PRIMARY_KEY"gorm:"-"

3 表名映射

Userusers

实现 Tabler 接口 (TableName 不支持动态变化,它会被缓存下来以便后续使用。)

type Tabler interface {
    TableName() string
}

// TableName 会将 User 的表名重写为 `profiles`
func (User) TableName() string {
  return "profiles"
}

动态表名,使用 Scopes。

func UserTable(user User) func (tx *gorm.DB) *gorm.DB {
  return func (tx *gorm.DB) *gorm.DB {
    if user.Admin {
      return tx.Table("admin_users")
    }

    return tx.Table("users")
  }
}

db.Scopes(UserTable(user)).Create(&user)

临时表名

db.Table("deleted_users")

默认方式 - 推荐

type User struct {
	ID int64 // 主键
	//通过在字段后面的标签说明,定义golang字段和表字段的关系
	//例如 `gorm:"column:username"` 标签说明含义是: Mysql表的列名(字段名)为username
	Username string `gorm:"column:username"`
	Password string `gorm:"column:password"`
	//创建时间,时间戳
	CreateTime int64 `gorm:"column:createtime"`
}

// 设置表名
func (u User) TableName() string {
	return "users"
}

4 Model

gorm.ModelID、CreatedAt、UpdatedAt、DeletedAt
// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}
CreatedAt、UpdatedAt/
autoCreateTime、autoUpdateTime
timetime.Timeint

例子:

type User struct {
  // 默认创建时间字段, 在创建时,
  // 如果该字段值为零值,则使用当前时间填充
  CreatedAt time.Time 
  // 默认更新时间字段, 
  // 在创建时该字段值为零值或者在更新时,
  // 使用当前时间戳秒数填充
  UpdatedAt int       
  // 自定义字段, 使用时间戳填纳秒数充更新时间
  Updated   int64 `gorm:"autoUpdateTime:nano"` 
  // 自定义字段, 使用时间戳毫秒数填充更新时间
  Updated   int64 `gorm:"autoUpdateTime:milli"` 
  // 自定义字段, 使用时间戳秒数填充创建时间
  Created   int64 `gorm:"autoCreateTime"`      
}

可以将它嵌入到您的结构体中,以包含这几个字段,比如:

type User struct {
  gorm.Model
  Name string
}

// 等效于
type User struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
  Name string
}
embedded
type Author struct {
    Name  string
    Email string 
}

type Blog struct {
  ID      int
  Author  Author `gorm:"embedded"`
  Upvotes int32
}
// 等效于
type Blog struct {
  ID    int64
  Name  string
  Email string
  Upvotes  int32
}
embeddedPrefixdb
type Blog struct {
  ID      int
  Author  Author `gorm:"embedded;embeddedPrefix:author_"`
  Upvotes int32
}

// 等效于
type Blog struct {
  ID          int64
  AuthorName  string
  AuthorEmail string
  Upvotes     int32
}

5. 数据库连接

GORM 官方支持的数据库类型有:

  • MySQL
  • PostgreSQL
  • SQlite
  • SQL Server

连接数据库主要是两个步骤:

gorm.Open

5.1 DSN

dsndsn

格式:

[username[:password]@][protocol[(address)]]/dbname[?param1=value1&...&paramN=valueN]

mysql 的 dsn 的一些例子:

//mysql dsn格式
//涉及参数:
//username   数据库账号
//password   数据库密码
//host       数据库连接地址,可以是Ip或者域名
//port       数据库端口
//Dbname     数据库名
username:password@tcp(host:port)/Dbname?charset=utf8&parseTime=True&loc=Local
//填上参数后的例子
//username = root
//password = 123456
//host     = localhost
//port     = 3306
//Dbname   = gorm
//后面K/V键值对参数含义为:
//  charset=utf8 客户端字符集为utf8
//  parseTime=true 支持把数据库datetime和date类型转换为golang的time.Time类型
//  loc=Local 使用系统本地时区
root:123456@tcp(localhost:3306)/gorm?charset=utf8&parseTime=True&loc=Local
// gorm 设置 mysql 连接超时参数
//开发的时候经常需要设置数据库连接超时参数,gorm是通过dsn的timeout参数配置
//例如,设置10秒后连接超时,timeout=10s
//下面是完成的例子
root:123456@tcp(localhost:3306)/gorm?charset=utf8&parseTime=True&loc=Local&timeout=10s
//设置读写超时时间
// readTimeout - 读超时时间,0代表不限制
// writeTimeout - 写超时时间,0代表不限制
root:123456@tcp(localhost:3306)/gorm?charset=utf8&parseTime=True&loc=Local&timeout=10s&readTimeout=30s&writeTimeout=60s

要支持完整的 UTF-8 编码,您需要将 charset=utf8 更改为 charset=utf8mb4。

5.2 连接数据库

import (
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

func main() {
  // 参考 https://github.com/go-sql-driver/mysql#dsn-data-source-name 获取详情
  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 驱动程序提供了 一些 高级配置 可以在初始化过程中使用,例如:

db, err := gorm.Open(mysql.New(mysql.Config{
  // DSN data source name
  DSN: "gorm:gorm@tcp(127.0.0.1:3306)/gorm?charset=utf8&parseTime=True&loc=Local", 
  // string 类型字段的默认长度
  DefaultStringSize: 256, 
  // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
  DisableDatetimePrecision: true,
  // 重命名索引时采用删除并新建的方式,
  // MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
  DontSupportRenameIndex: true, 
  // 用 `change` 重命名列,
  // MySQL 8 之前的数据库和 MariaDB 不支持重命名列
  DontSupportRenameColumn: true, 
  // 根据当前 MySQL 版本自动配置
  SkipInitializeWithVersion: false, 
}), &gorm.Config{})

GORM 允许通过 DriverName 选项自定义 MySQL 驱动,例如:

import (
  _ "example.com/my_mysql_driver"
  "gorm.io/driver/mysql"
  "gorm.io/gorm"
)

db, err := gorm.Open(mysql.New(mysql.Config{
  DriverName: "my_mysql_driver",
  DSN: "gorm:gorm@tcp(localhost:9910)/gorm?charset=utf8&parseTime=True&loc=Local", // data source name, 详情参考:https://github.com/go-sql-driver/mysql#dsn-data-source-name
}), &gorm.Config{})

5.3 调试模式

db.Debug()

5.4 连接池配置

sqlDB, _ := db.DB()

//设置数据库连接池参数
//设置数据库连接池最大连接数
sqlDB.SetMaxOpenConns(100)   
//连接池最大允许的空闲连接数,
//如果没有sql任务需要执行的连接数大于20,
//超过的连接会被连接池关闭
sqlDB.SetMaxIdleConns(20)