【GORM】初探gorm模型,字段标签与go案例

embedded/2025/1/23 16:52:48/

GORM是什么?

  • GORM 是一个Go 语言 ORM(对象关系映射)库,它让我们可以使用结构体来操作数据库,而无需编写SQL 语句

GORM 模型与字段标签详解

在 GORM 中,模型是数据库表的抽象表示,字段标签(Tag)则用于指定模型字段与数据库字段之间的映射规则及行为。


1. 模型定义

模型是由 Go 的结构体定义的,它表示数据库中的一张表。GORM 默认遵循约定优于配置的原则,提供了很多自动化功能。

基本模型示例

type User struct {ID        uint      `gorm:"primaryKey"` // 主键Name      string    `gorm:"size:100"`   // 字符串最大长度为 100Email     string    `gorm:"unique"`     // 唯一字段Age       uint8     `gorm:"check:age >= 0"` // 年龄必须非负CreatedAt time.Time // 创建时间UpdatedAt time.Time // 更新时间
}

GORM 的默认约定

  1. 使用结构体名的复数形式(蛇形命名)作为表名。
    • 例如:User -> 表名为 users
  2. 字段名会转换为蛇形命名作为列名。
    • 例如:CreatedAt -> 列名为 created_at
  3. 自动管理 CreatedAtUpdatedAt 字段。

2. 字段标签详解

GORM 提供了丰富的字段标签,帮助我们定制模型字段的行为。以下是常用标签的分类及示例。

2.1 主键和自增

  • primaryKey:设置主键。
  • autoIncrement:设置字段为自增。
type Product struct {ID    uint   `gorm:"primaryKey;autoIncrement"`Name  stringPrice float64
}

效果ID 字段为自增主键。


2.2 字段属性

  • size:设置字符串类型字段的最大长度。
  • not null:设置字段不能为空。
  • default:设置字段的默认值。
  • unique:设置字段为唯一约束。
type Customer struct {ID      uintName    string `gorm:"size:50;not null"`    // 最长 50 字符,不能为空Email   string `gorm:"unique;not null"`    // 唯一且不能为空Status  string `gorm:"default:'active'"`   // 默认值为 'active'
}

效果

  • NameEmail 字段必须有值。
  • 插入记录时,未显式设置 Status 的值时,将使用默认值。

2.3 外键与关联

  • foreignKey:定义外键字段。
  • references:指定外键引用的字段。
  • constraint:设置外键的约束行为。
type Order struct {ID         uintCustomerID uint        `gorm:"not null"`Customer   Customer    `gorm:"foreignKey:CustomerID;references:ID;constraint:OnUpdate:CASCADE,OnDelete:SET NULL"`
}

效果

  • Order.CustomerIDCustomer.ID 的外键。
  • 更新 Customer.ID 时级联更新,删除 Customer 时将 CustomerID 设为 NULL。

2.4 时间字段

  • autoCreateTime:自动设置为记录创建时间。
  • autoUpdateTime:自动设置为记录更新时间。
type Post struct {ID        uintTitle     stringCreatedAt int64 `gorm:"autoCreateTime"` // 使用 Unix 时间戳UpdatedAt int64 `gorm:"autoUpdateTime:nano"` // 使用纳秒时间戳
}

2.5 嵌套结构体

GORM 支持将结构体嵌套到模型中,通过标签自定义嵌套字段的列名前缀。

type Author struct {Name  stringEmail string
}type Blog struct {ID      uintAuthor  Author `gorm:"embedded;embeddedPrefix:author_"`Content string
}

效果

  • Author 的字段会被展开,数据库表的列名为 author_nameauthor_email

3. 实际案例:用户与订单系统

以下是一个用户和订单的实际案例,展示如何使用模型和字段标签。

模型定义

type User struct {ID        uint       `gorm:"primaryKey"`Name      string     `gorm:"size:100;not null"`Email     string     `gorm:"uniqueIndex;not null"`Orders    []Order    `gorm:"foreignKey:UserID"`CreatedAt time.TimeUpdatedAt time.Time
}type Order struct {ID        uint       `gorm:"primaryKey"`UserID    uint       `gorm:"not null"`Amount    float64    `gorm:"not null"`Status    string     `gorm:"default:'pending'"`CreatedAt time.Time
}

数据库迁移

使用 AutoMigrate 自动生成表结构:

db.AutoMigrate(&User{}, &Order{})

数据操作

  1. 插入数据
user := User{Name: "Alice", Email: "alice@example.com"}
db.Create(&user)order := Order{UserID: user.ID, Amount: 99.99}
db.Create(&order)
  1. 查询数据
var user User
db.Preload("Orders").First(&user)
fmt.Printf("用户信息: %+v\\n", user)

4. 总结

标签描述示例

| primaryKey | 设置字段为主键 | gorm:\"primaryKey\" |
| size | 设置字符串字段长度 | gorm:\"size:255\" |
| not null | 设置字段不能为空 | gorm:\"not null\" |
| unique | 设置字段唯一性约束 | gorm:\"unique\" |
| autoCreateTime| 自动记录创建时间 | gorm:\"autoCreateTime\" |

| foreignKey | 定义外键字段 | gorm:\"foreignKey:UserID\"|

| embedded | 嵌套结构体字段 | gorm:\"embedded\" |


go案例展示

conn.go

package _caseimport ("fmt""gorm.io/driver/mysql""gorm.io/gorm""gorm.io/gorm/logger""log""os""time"
)var DB *gorm.DB/*
用户名和密码:root:123456
root 是数据库用户名。
123456 是数据库密码。
网络协议和地址:@tcp(192.168.88.131:3306)
@tcp 表示使用 TCP 协议进行连接。
192.168.88.131 是数据库服务器的 IP 地址。
3306 是 MySQL 默认端口号。
数据库名称:/mydb
mydb 是要连接的数据库名称。
查询参数:
charset=utf8mb4:指定字符集为 utf8mb4,支持完整的 Unicode 编码,包括表情符号等。
parseTime=True:将时间字段解析为 Go 的 time.Time 类型。
loc=Local:设置时区为本地时区。// 保存与数据库的连接实例
*/
var dsn = "root:123456@tcp(192.168.88.131:3306)/mydb?charset=utf8mb4&parseTime=True&loc=Local" // 数据源名称(DSN)// 为了提高安全性,避免硬编码敏感信息(如用户名和密码),可以使用环境变量来存储这些信息。
func getDSN() string {return fmt.Sprintf("%s:%s@tcp(%s:%s)/%s?charset=utf8mb4&parseTime=True&loc=Local",os.Getenv("DB_USER"),os.Getenv("DB_PASSWORD"),os.Getenv("DB_HOST"),os.Getenv("DB_PORT"),os.Getenv("DB_NAME"))
}// 使用 GORM 库连接 MySQL 数据库,并配置数据库连接池。
func init() {var err errorDB, err = gorm.Open(mysql.New(mysql.Config{ // gorm.Open 打开数据库连接 ,第一个参数mysql.Config是mysql配置对象DSN:               dsn,DefaultStringSize: 256,}), &gorm.Config{ // 第二个参数gorm.Config gorm配置Logger: logger.Default.LogMode(logger.Info), // 设置日志级别为Info// 开启预编译,提高后续调用速度// 开启预编译情况,不支持嵌套事务// PrepareStmt: true})if err != nil {log.Println(err)return}setPool(DB)
}// 设置数据库连接池
func setPool(db *gorm.DB) {sqlDB, err := db.DB() // 获取底层的*sql.DBif err != nil {log.Println(err)return}sqlDB.SetMaxOpenConns(100)          // 设置最大打开连接数sqlDB.SetMaxIdleConns(10)           // 设置最大空闲连接数sqlDB.SetConnMaxLifetime(time.Hour) // 设置连接最大生命周期
}

models.go

package _caseimport "gorm.io/gorm"// init函数在程序启动时初始化数据库迁移
// 使用了AutoMigrate方法来自动迁移Teacher和Course模型
// 确保了表结构与 Go 结构体定义保持同步
func init() {DB.Migrator().AutoMigrate(Teacher{}, Course{}) // migrator 迁移器 autoMigrate 自动迁移
}type Roles []string // 存储教师的角色信息
// Teacher 结构体代表了一个教师实体,用于在数据库中存储教师的相关信息。
// 通过 GORM 标签,定义了各个字段在数据库中的行为和约束。
type Teacher struct {gorm.Model         // 继承自 GORM 的默认模型,包含 ID, CreatedAt, UpdatedAt, DeletedAt 字段Name       string  `gorm:"size:256"`                      // 教师的姓名,最多256个字符Email      string  `gorm:"size:256"`                      // 教师的电子邮件地址,最多256个字符Salary     float64 `gorm:"scale:2;precision:7"`           // 教师的工资,使用7位精度和2位小数表示Age        uint8   `gorm:"check:age>30"`                  // 教师的年龄,数据库中有一个检查约束确保年龄大于30Birthday   int64   `gorm:"serializer:unixtime;type:time"` // 教师的生日,以Unix时间戳的形式存储Roles      Roles   `gorm:"serializer:json"`               // 教师的角色,以JSON格式序列化存储JobInfo    Job     `gorm:"embedded;embeddedPrefix:job_"`  // 嵌入的Job结构体,表示教师的职业信息,字段名前缀为job_JobInfo2   Job     `gorm:"type:bytes;serializer:gob"`     // 另一种形式的教师职业信息存储,使用GOB序列化方式存储为字节类型
}type Job struct {Title    stringLocation string
}// Course 结构体代表了一个课程实体,包括课程的基本信息及其与用户的关系。
// 该结构体使用了gorm.Model,这意味着它包含了通用的字段如ID、创建时间、更新时间和删除时间,用于ORM操作。
type Course struct {// gorm.Model 嵌入式通用模型,提供基础的ORM功能。gorm.Model// Name 字段表示课程的名称,使用gorm注释指定最大长度为256字符。Name string `gorm:"size:256"`// Price 字段表示课程的价格,其中scale:2表示小数点后保留两位,precision:7表示总共可以存储7位数字(包括小数点后的数字)。Price float64 `gorm:"scale:2;precision:7"`// UserID 字段表示创建或关联该课程的用户ID,使用gorm注释指定其数据库中的类型为int。UserID uint `gorm:"type:int"`
}

main.go

package mainimport (_ "golang15-gorm/case"
)func main() {}

在这里插入图片描述


https://github.com/0voice


http://www.ppmy.cn/embedded/156348.html

相关文章

反向代理模块1

1 概念 1.1 反向代理概念 反向代理是指以代理服务器来接收客户端的请求,然后将请求转发给内部网络上的服务器,将从服务器上得到的结果返回给客户端,此时代理服务器对外表现为一个反向代理服务器。 对于客户端来说,反向代理就相当于…

DeepSeek R1发布综述:开源大语言模型的推理能力新标杆

引言 2025年1月20日,人工智能公司DeepSeek-AI正式发布了全新的大语言模型DeepSeek R1和DeepSeek R1-Zero。这一重磅发布标志着开源大型语言模型(LLMs)在推理能力上的重大突破。DeepSeek R1系列不仅通过创新的强化学习技术实现了推理能力的显…

【Spring Boot】Spring原理:Bean的作用域和生命周期

目录 Spring原理 一. 知识回顾 1.1 回顾Spring IOC1.2 回顾Spring DI1.3 回顾如何获取对象 二. Bean的作用域三. Bean的生命周期 Spring原理 一. 知识回顾 在之前IOC/DI的学习中我们也用到了Bean对象,现在先来回顾一下IOC/DI的知识吧! 首先Spring I…

VR vs AR:哪种技术更有潜力改变未来?

AR与VR的未来之争 在我们的日常生活中,技术的更新换代仿佛只需一瞬间。而在众多技术中,虚拟现实(VR)和增强现实(AR)如同璀璨的明星,吸引着无数眼球。你是否曾因选择哪种技术更具潜力而感到困惑…

数据结构之堆排序

文章目录 堆排序版本一图文理解 版本二向下调整建堆向上调整建堆 排升/降序升序 堆排序 版本一 基于已有数组建堆取堆顶元素并删除堆顶元素重新建大根堆,完成排序版本。 图文理解 版本二 前提:必须提供有现成的数据结构堆 数组建堆,首尾…

【C++】在线五子棋对战项目网页版

目录 1.Websocket 1.1.Websocket的简单认识 1.2.什么是轮询呢? 1.3.websocket协议切换过程 1.4.websocketpp库常用接口认识 1.5.websocketpp库搭建服务器流程 1.6.websocketpp库搭建服务器 2.mysqlclient库-接口认识 3.项目模块的划分: 4.项目…

C语言——文件操作

目录 前言 一什么是文件 1程序文件 2数据文件 3文件名 二文件的打开与关闭 1文件指针 2fopen 3fclose 三文件的读与写 1文件的顺序读写 1.1fputc fgetc 1.2fputs fgets 1.3fprintf fscanf 1.4fwrite fread 1.5文本文件和二进制文件 2文件的任意读写 1fseek …

state的异步跟新

预测下刷新页面后,页面上会有啥数字出现 import React, { useState, useEffect } from "react";const Bpp () > {const [data, setData] useState([]);// const [loading, setLoading] useState(true);const [errorData, setErrorData] useState(…