GoClub Pro

MySQL-gorm-概要

最近更新:2026-10-24
本页由同名 OneNote 笔记转换而来,可直接在线阅读;原始笔记文件见「Go语言相关笔记」页的原始链接。
笔记图片

1.save,update,create……才会对数据库更新,save语句浪费资源

GORM 要求使用 column: 指定列名,size: 指定长度,或 type: 精确指定 SQL 类型。

 

 

MySQL 基础知识

作用

MySQL是一个开源的关系型数据库管理系统,用于存储、管理和检索结构化数据。它支持SQL语言,提供ACID事务特性,广泛应用于Web应用开发。

 

基础语法详解

1. 数据库操作

 

-- 创建数据库

CREATE DATABASE database_name

[CHARACTER SET charset_name]

[COLLATE collation_name];

 

-- 使用数据库

USE database_name;

 

-- 删除数据库

DROP DATABASE database_name;

 

2. 表操作

 

-- 创建表

CREATE TABLE table_name (

column1 datatype [constraints],

column2 datatype [constraints],

...

[table_constraints]

);

 

-- 参数解释:

-- datatype: INT, VARCHAR(n), TEXT, DATE, DATETIME, DECIMAL(p,s)等

-- constraints:

-- PRIMARY KEY - 主键

-- NOT NULL - 非空

-- UNIQUE - 唯一

-- AUTO_INCREMENT - 自增

-- DEFAULT value - 默认值

-- FOREIGN KEY - 外键

 

-- 示例

CREATE TABLE users (

id INT AUTO_INCREMENT PRIMARY KEY,

username VARCHAR(50) NOT NULL UNIQUE,

email VARCHAR(100) NOT NULL,

age INT DEFAULT 0,

created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP

);

 

3. 数据操作语言 (DML)

 

-- INSERT - 插入数据

INSERT INTO table_name (column1, column2, ...)

VALUES (value1, value2, ...);

 

-- SELECT - 查询数据

SELECT column1, column2, ...

FROM table_name

[WHERE condition]

[ORDER BY column [ASC|DESC]]

[LIMIT number];

 

-- UPDATE - 更新数据

UPDATE table_name

SET column1 = value1, column2 = value2, ...

[WHERE condition];

 

-- DELETE - 删除数据

DELETE FROM table_name

[WHERE condition];

 

4. 高级查询

 

-- JOIN 连接查询

SELECT columns

FROM table1

[INNER|LEFT|RIGHT] JOIN table2

ON table1.column = table2.column;

 

-- 聚合函数

SELECT COUNT(*), AVG(column), SUM(column), MAX(column), MIN(column)

FROM table_name

[GROUP BY column];

 

-- 子查询

SELECT * FROM table1

WHERE column IN (SELECT column FROM table2 WHERE condition);

 

GORM 基础知识

作用

GORM是Go语言的ORM(对象关系映射)库,它提供了面向对象的方式操作数据库,简化了数据库操作,支持MySQL、PostgreSQL、SQLite等数据库。

 

基础语法详解

1. 模型定义

 

import "gorm.io/gorm"

 

// 基础模型

type User struct {

gorm.Model // 包含ID, CreatedAt, UpdatedAt, DeletedAt

Name string `gorm:"type:varchar(100);not null"`

Email string `gorm:"type:varchar(100);uniqueIndex"`

Age int `gorm:"default:18"`

IsActive bool `gorm:"default:true"`

}

 

// 标签说明:

// type: 字段类型

// not null: 非空约束

// uniqueIndex: 唯一索引

// default: 默认值

// primaryKey: 主键

// autoIncrement: 自增

 

2. 连接数据库

 

import (

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

 

// 函数签名: gorm.Open(dialector, &gorm.Config{})

dsn := "user:password@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=Local"

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

 

3. 自动迁移

 

// 函数签名: db.AutoMigrate(dst ...interface{}) error

err := db.AutoMigrate(&User{}, &Product{})

 

 

4. CRUD 操作

Create – 创建记录

// 函数签名: db.Create(value interface{}) *gorm.DB

user := User{Name: "John", Email: "[email protected]"}

result := db.Create(&user)

 

// 批量创建

users := []User{

{Name: "Alice", Email: "[email protected]"},

{Name: "Bob", Email: "[email protected]"},

}

db.Create(&users)

 

Read – 查询记录

 

// 函数签名: db.First(dest interface{}, conds ...interface{}) *gorm.DB

var user User

db.First(&user, 1) // 根据主键查询

db.First(&user, "name = ?", "John")

 

// 查询所有记录

var users []User

db.Find(&users)

 

// 条件查询

db.Where("age > ?", 18).Find(&users)

db.Where("name LIKE ?", "%john%").Find(&users)

 

// 排序和限制

db.Order("created_at desc").Limit(10).Find(&users)

 

 

Update – 更新记录

 

// 函数签名: db.Model(dest interface{}).Updates(values interface{}) *gorm.DB

db.Model(&user).Update("Name", "John Updated")

db.Model(&user).Updates(User{Name: "New Name", Age: 30})

db.Model(&user).Updates(map[string]interface{}{"Name": "John", "Age": 25})

 

 

Delete – 删除记录

 

// 函数签名: db.Delete(dest interface{}, conds ...interface{}) *gorm.DB

db.Delete(&user) // 软删除(如果模型有DeletedAt字段)

db.Where("age < ?", 18).Delete(&User{}) // 条件删除

 

 

5. 关联关系

 

// 一对一关系

type User struct {

gorm.Model

Profile Profile

}

 

type Profile struct {

gorm.Model

UserID uint

Bio string

}

 

// 一对多关系

type User struct {

gorm.Model

Orders []Order

}

 

type Order struct {

gorm.Model

UserID uint

Amount float64

}

 

// 多对多关系

type User struct {

gorm.Model

Languages []Language `gorm:"many2many:user_languages;"`

}

 

type Language struct {

gorm.Model

Name string

}

 

 

6. 事务处理

 

// 函数签名: db.Transaction(fc func(tx *gorm.DB) error) error

err := db.Transaction(func(tx *gorm.DB) error {

if err := tx.Create(&user1).Error; err != nil {

return err

}

if err := tx.Create(&user2).Error; err != nil {

return err

}

return nil

})

 

7. 钩子函数(Hooks)

 

type User struct {

gorm.Model

Name string

}

 

// 创建前的钩子

func (u *User) BeforeCreate(tx *gorm.DB) error {

if u.Name == "" {

return errors.New("name cannot be empty")

}

return nil

}

 

// 更新前的钩子

func (u *User) BeforeUpdate(tx *gorm.DB) error {

u.UpdatedAt = time.Now()

return nil

}

 

完整示例

 

package main

 

import (

"fmt"

"log"

"gorm.io/driver/mysql"

"gorm.io/gorm"

)

 

type User struct {

ID uint `gorm:"primaryKey"`

Name string `gorm:"size:100;not null"`

Email string `gorm:"size:100;uniqueIndex"`

CreatedAt int64

}

 

func main() {

dsn := "root:password@tcp(127.0.0.1:3306)/testdb?charset=utf8mb4&parseTime=True&loc=Local"

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})

if err != nil {

log.Fatal(err)

}

 

// 自动迁移

db.AutoMigrate(&User{})

 

// 创建用户

user := User{Name: "Alice", Email: "[email protected]"}

db.Create(&user)

 

// 查询用户

var result User

db.First(&result, user.ID)

fmt.Printf("User: %+v\n", result)

 

// 更新用户

db.Model(&result).Update("Name", "Alice Updated")

 

// 删除用户

db.Delete(&result)

}

 

 

MySQL学习资源

B站视频: 搜索"MySQL从入门到精通"、"MySQL实战教程"

推荐课程:

"MySQL数据库全套教程" - 涵盖基础到高级

"SQL语句精讲" - 重点学习SQL语法

"MySQL性能优化" - 进阶学习

GORM学习资源

B站视频: 搜索"GORM教程"、"Go语言ORM实战"

官方文档: https://gorm.io/docs/

推荐课程:

"GORM从入门到实战"

"Go语言Web开发+GORM"

附件文档全文:GORM 文档与 CONF 文档

GORM 全面详细讲解

Go语言GORM全面详细讲解

GORM(Go ORM)是Go语言生态中最流行的全功能ORM框架,专为Go语言设计,支持MySQL、PostgreSQL、SQLite、SQL Server等主流数据库,提供了优雅的链式调用、自动迁移、关联查询、事务管理等核心能力,大幅降低Go语言操作数据库的开发成本,是企业级Go项目的首选数据库操作框架。

一、GORM核心版本说明

目前GORM有两个主要版本,推荐新项目直接使用GORM v2(功能更完善、性能更优、API更统一),v1已进入维护阶段,不再新增功能:

  • GORM v1:旧版核心包github.com/jinzhu/gorm,仅支持Go 1.12+,部分功能设计冗余;
  • GORM v2:新版核心包gorm.io/gorm,要求Go 1.16+,重构了底层架构,新增批量操作、预加载优化、自定义插件等功能,是当前的主流版本。

下文所有讲解均基于GORM v2。

二、快速入门:安装与基础使用

2.1 安装核心包与数据库驱动

GORM v2将核心框架与数据库驱动解耦,需分别安装核心包和对应数据库的驱动(以最常用的MySQL为例):

Bash
# 安装GORM v2核心包
go get gorm.io/gorm
# 安装MySQL驱动(GORM官方推荐的mysql驱动,基于go-sql-driver/mysql封装)
go get gorm.io/driver/mysql

其他数据库驱动安装:

Bash
# PostgreSQL
go get gorm.io/driver/postgres
# SQLite
go get gorm.io/driver/sqlite
# SQL Server
go get gorm.io/driver/sqlserver

2.2 数据库连接

通过gorm.Open建立数据库连接,第一个参数为驱动实例,第二个参数为GORM配置项(gorm.Config{})。

MySQL连接示例(最常用)

Go
package main

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

func main() {
// 1. 构造MySQL DSN(数据源名称),格式:user:password@tcp(host:port)/dbname?charset=utf8mb4&parseTime=True&loc=Local
// 说明:parseTime=True 让GORM能解析MySQL的时间类型,loc=Local 使用本地时区
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm_demo?charset=utf8mb4&parseTime=True&loc=Local"

// 2. 建立数据库连接,返回*gorm.DB(GORM核心操作对象,全局复用即可,无需每次创建)
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("数据库连接失败:" + err.Error())
}

// 3. (可选)获取底层sql.DB,设置连接池参数(关键:避免高并发下连接耗尽)
sqlDB, _ := db.DB()
// 设置最大打开连接数(同时与数据库建立的最大连接数)
sqlDB.SetMaxOpenConns(100)
// 设置最大空闲连接数(连接池中保持的空闲连接数)
sqlDB.SetMaxIdleConns(20)
}

关键注意:*gorm.DB是并发安全的,项目中建议全局初始化一次,所有goroutine复用即可。

2.3 定义模型(Model)与自动迁移

GORM通过Go结构体映射数据库表,称为「模型(Model)」,支持通过结构体标签(tag) 配置字段与列的映射关系,同时提供AutoMigrate实现「表结构自动同步」(仅创建表、添加列/索引,不会删除/修改现有列,避免数据丢失)。

基础模型定义(含核心tag说明)

Go
package main

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

// User 模型:映射数据库的users表(GORM默认蛇形命名,结构体首字母大写→表名小写复数)
// 核心标签:gorm:"xxx",用于配置字段/列的映射关系
type User struct {
ID uint64 `gorm:"primaryKey;autoIncrement"` // 主键,自增(uint64对应MySQL bigint)
Name string `gorm:"size:50;not null;comment:用户名"` // 长度50,非空,字段注释
Age int `gorm:"default:0;comment:年龄"` // 默认值0
Email string `gorm:"unique;size:100;comment:邮箱"` // 唯一索引,长度100
CreatedAt time.Time // GORM默认字段:创建时间,自动维护
UpdatedAt time.Time // GORM默认字段:更新时间,自动维护
DeletedAt gorm.DeletedAt `gorm:"index"` // 软删除字段:带索引,开启软删除后,删除操作变为更新该字段
}

func main() {
dsn := "root:123456@tcp(127.0.0.1:3306)/gorm_demo?charset=utf8mb4&parseTime=True&loc=Local"
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{})

// 自动迁移:根据模型创建/更新表结构(仅新增,不删除)
// 传模型指针,支持同时迁移多个模型:db.AutoMigrate(&User{}, &Article{})
err := db.AutoMigrate(&User{})
if err != nil {
panic("表结构迁移失败:" + err.Error())
}
}

常用GORM Tag说明(开发必备)

Tag键

作用

primaryKey

标记该字段为主键(支持复合主键:多个字段加该tag)

autoIncrement

主键自增(仅支持数值类型)

size:n

设置字段长度(如size:50,对应MySQL varchar(50))

not null

设置字段非空

default:val

设置字段默认值(如default:0、default:'unknown')

unique

为字段创建唯一索引

index

为字段创建普通索引

comment:xxx

为字段添加注释(生成表结构时自动带上)

column:xxx

自定义列名(如gorm:"column:user_name",覆盖默认蛇形命名)

type:xxx

自定义字段类型(如gorm:"type:longtext",对应MySQL longtext)

-

忽略该字段(不映射到数据库列)

三、GORM核心CURD操作

GORM提供优雅的链式调用实现增删改查,核心操作均基于*gorm.DB,且支持条件链式拼接(如Where+Limit+Order)。

3.1 新增(Create):单条/批量插入

单条插入

Go
// 创建单条记录:传模型实例指针
user := User{Name: "张三", Age: 20, Email: "[email protected]"}
result := db.Create(&user) // 插入后,主键ID会自动赋值到user.ID

// 插入结果判断
if result.Error != nil {
panic("插入失败:" + result.Error.Error())
}
fmt.Printf("插入成功,自增ID:%d,影响行数:%d\n", user.ID, result.RowsAffected)

批量插入(推荐:性能远高于循环单插)

Go
// 方式1:切片批量插入(推荐,一次SQL请求)
users := []User{
{Name: "李四", Age: 22, Email: "[email protected]"},
{Name: "王五", Age: 25, Email: "[email protected]"},
}
db.Create(&users) // 插入后,每个元素的ID都会自动赋值

// 方式2:分批次批量插入(适合超大量数据,避免SQL语句过长)
// CreateInBatches(切片, 批次大小),如每次插入100条
db.CreateInBatches(users, 100)

3.2 查询(Query):单条/多条/条件/排序/分页

GORM查询支持链式条件拼接,核心方法:First(单条,按主键升序)、Take(单条,无排序)、Last(单条,按主键降序)、Find(多条,返回切片)。

3.2.1 基础查询

Go
var user User
var users []User

// 1. 根据主键查询单条(主键不存在返回error)
db.First(&user, 1) // 查询ID=1的用户
db.First(&user, "id = ?", 1) // 等价写法,占位符?

// 2. 无主键条件查询单条
db.Where("name = ?", "张三").First(&user)

// 3. 查询多条记录(返回切片,无结果时error为nil,切片长度0)
db.Find(&users) // 查询所有用户
db.Where("age > ?", 20).Find(&users) // 查询年龄>20的所有用户

// 4. 查询指定字段(避免查询全字段,提升性能)
// Select("字段1, 字段2"),或传切片[]string{"name", "age"}
db.Select("name", "age").Where("id = ?", 1).First(&user)

// 5. 排序:Order("字段 排序方式"),升序ASC(默认),降序DESC
db.Order("age DESC, id ASC").Find(&users)

// 6. 分页:Limit(每页条数).Offset(偏移量),偏移量=(页码-1)*每页条数
// 示例:查询第2页,每页10条
page := 2
pageSize := 10
db.Limit(pageSize).Offset((page - 1) * pageSize).Find(&users)

3.2.2 常用条件查询(Where的多种用法)

GORM的Where支持字符串占位符、结构体、Map三种条件格式,满足不同场景需求:

Go
var user User
var users []User

// 方式1:字符串占位符(推荐,支持复杂条件,避免注入)
db.Where("name = ? AND age > ?", "张三", 18).First(&user)
db.Where("age IN (?)", []int{20,22,25}).Find(&users) // IN条件
db.Where("created_at BETWEEN ? AND ?", start, end).Find(&users) // 范围条件

// 方式2:结构体条件(自动忽略零值:0、""、false、nil等)
db.Where(&User{Name: "张三", Age: 20}).First(&user) // 仅查询name=张三且age=20的记录

// 方式3:Map条件(不忽略零值,支持自定义列名)
db.Where(map[string]interface{}{"name": "张三", "age": 0}).Find(&users) // 可查询age=0的记录

// 链式多条件:多个Where自动拼接为AND
db.Where("name = ?", "张三").Where("age > ?", 18).First(&user)

// OR条件:用Or()拼接
db.Where("name = ?", "张三").Or("age > ?", 25).Find(&users)

3.3 更新(Update):单字段/多字段/条件更新

GORM更新分为模型更新和直接更新,推荐使用条件+指定字段更新,避免误更全部数据。

3.3.1 单字段更新

Go
// 方式1:Update("字段名", 新值) + 条件(推荐)
db.Model(&User{}).Where("id = ?", 1).Update("name", "张三_更新")

// 方式2:根据模型主键更新(模型必须有主键值)
user := User{ID: 1}
db.Model(&user).Update("age", 21)

3.3.2 多字段更新

Go
// 方式1:Updates(结构体)(忽略零值,仅更新非零字段)
db.Model(&User{}).Where("id = ?", 1).Updates(User{Name: "张三_新名", Age: 22})

// 方式2:Updates(Map)(不忽略零值,支持所有字段更新)
db.Model(&User{}).Where("id = ?", 1).Updates(map[string]interface{}{
"name": "张三_Map",
"age": 23,
"email": "", // 可更新为零值
})

// 方式3:更新指定字段(Select)+ 忽略指定字段(Omit)
// 仅更新name和age,忽略其他字段
db.Model(&User{}).Where("id = ?", 1).Select("name", "age").Updates(User{Name: "张三", Age: 20, Email: "[email protected]"})
// 更新所有字段,除了email
db.Model(&User{}).Where("id = ?", 1).Omit("email").Updates(User{Name: "张三", Age: 20, Email: "[email protected]"})

3.3.3 批量更新

Go
// 给所有年龄>20的用户,年龄+1
db.Model(&User{}).Where("age > ?", 20).Update("age", gorm.Expr("age + ?", 1))

注意:无条件的更新/删除会被GORM阻止(防止误操作全表),如需强制执行,需添加Unscoped()或指定条件。

3.4 删除(Delete):物理删除/软删除

GORM支持物理删除(真正删除数据库记录)和软删除(仅更新DeletedAt字段,记录仍存在,查询时自动过滤),默认开启软删除(模型包含gorm.DeletedAt字段时)。

3.4.1 软删除(默认)

Go
// 1. 单条软删除:根据主键
db.Delete(&User{}, 1) // 删除ID=1的用户,实际执行:UPDATE users SET deleted_at = NOW() WHERE id=1
// 2. 条件软删除
db.Where("age < ?", 18).Delete(&User{})

// 3. 查询软删除的记录:Unscoped() 关闭软删除过滤
var delUser User
db.Unscoped().First(&delUser, 1) // 可查询到已软删除的ID=1的用户

// 4. 批量软删除
db.Delete(&[]User{}, []int64{2,3,4}) // 删除ID=2、3、4的用户

3.4.2 物理删除(真正删除)

Go
// 方式1:Unscoped() + Delete,强制物理删除
db.Unscoped().Delete(&User{}, 1) // 实际执行:DELETE FROM users WHERE id=1
// 方式2:条件物理删除
db.Unscoped().Where("age < ?", 18).Delete(&User{})

四、高级特性

4.1 事务管理

GORM支持手动事务和自动事务,满足不同场景的事务需求,核心基于Begin()开启事务,返回*gorm.DB事务对象,通过Commit()提交、Rollback()回滚。

4.1.1 手动事务(推荐,灵活控制)

Go
// 1. 开启事务
tx := db.Begin()
if tx.Error != nil {
panic("开启事务失败:" + tx.Error.Error())
}

// 2. 执行事务内的操作(必须使用tx对象,而非原db对象)
user1 := User{Name: "事务用户1", Age: 30}
if err := tx.Create(&user1).Error; err != nil {
tx.Rollback() // 出错则回滚
panic("插入失败,事务回滚:" + err.Error())
}

user2 := User{Name: "事务用户2", Age: 35}
if err := tx.Create(&user2).Error; err != nil {
tx.Rollback() // 出错则回滚
panic("插入失败,事务回滚:" + err.Error())
}

// 3. 提交事务
if err := tx.Commit().Error; err != nil {
tx.Rollback()
panic("事务提交失败:" + err.Error())
}
fmt.Println("事务执行成功,插入用户ID:", user1.ID, user2.ID)

4.1.2 自动事务(简化版,适合简单场景)

通过Transaction(func(tx *gorm.DB) error)实现,函数内无错误则自动提交,有错误则自动回滚:

Go
err := db.Transaction(func(tx *gorm.DB) error {
// 执行事务操作
if err := tx.Create(&User{Name: "自动事务", Age: 28}).Error; err != nil {
return err // 返回错误,自动回滚
}
return nil // 返回nil,自动提交
})

if err != nil {
panic("自动事务失败:" + err.Error())
}

4.2 关联查询(一对一/一对多/多对多)

GORM支持主流的数据库关联关系,通过模型嵌套和Preload(预加载)实现关联查询,避免N+1查询问题(先查主表,再循环查关联表)。

示例:一对多关联(用户-文章,一个用户有多篇文章)

Go
// 1. 定义关联模型
type User struct {
ID uint64 `gorm:"primaryKey"`
Name string `gorm:"size:50"`
Articles []Article `gorm:"foreignKey:UserID"` // 一对多:关联Article的UserID字段
}

type Article struct {
ID uint64 `gorm:"primaryKey"`
Title string `gorm:"size:100"`
Content string
UserID uint64 `gorm:"index"` // 外键:关联User的ID
User User `gorm:"references:ID"` // 反向关联:引用User的主键ID
}

// 2. 预加载关联查询(一次查询主表+关联表,避免N+1)
var user User
// Preload("关联字段名") 预加载关联数据
db.Preload("Articles").First(&user, 1)
fmt.Printf("用户:%s,文章数:%d\n", user.Name, len(user.Articles))

// 3. 条件预加载:预加载符合条件的关联数据
db.Preload("Articles", "title LIKE ?", "%Go%").First(&user, 1) // 预加载用户1的Go相关文章

// 4. 嵌套预加载:预加载多层关联(如文章-评论)
// db.Preload("Articles.Comments").First(&user, 1)

4.3 原生SQL执行

对于复杂的查询(如多表联查、聚合查询、存储过程),GORM支持直接执行原生SQL,通过Raw和Exec实现:

Go
var users []User
var count int64

// 1. 原生查询:Raw("SQL语句", 占位符参数).Scan(结果指针)
db.Raw("SELECT id, name, age FROM users WHERE age > ?", 20).Scan(&users)

// 2. 原生聚合查询
db.Raw("SELECT COUNT(*) FROM users WHERE age > ?", 18).Scan(&count)
fmt.Println("年龄>18的用户数:", count)

// 3. 原生执行更新/删除:Exec("SQL语句", 占位符参数)
result := db.Exec("UPDATE users SET age = age + 1 WHERE id = ?", 1)
fmt.Println("影响行数:", result.RowsAffected)

五、GORM配置与最佳实践

5.1 常用GORM配置(gorm.Config{})

初始化连接时的gorm.Config{}支持多种配置,优化框架行为:

Go
db, _ := gorm.Open(mysql.Open(dsn), &gorm.Config{
SkipDefaultTransaction: true, // 关闭默认事务(GORM部分操作默认开启事务,关闭可提升性能)
NamingStrategy: schema.NamingStrategy{
TablePrefix: "t_", // 表名前缀,如User模型映射t_users表
SingularTable: true, // 表名单数,如User模型映射user表(默认复数)
NoLowerCase: false, // 是否关闭蛇形命名(默认开启,Name→name)
},
Logger: logger.Default.LogMode(logger.Info), // 开启日志,打印SQL语句(开发环境推荐)
})

5.2 开发最佳实践

  1. 全局复用*gorm.DB:*gorm.DB并发安全,项目中在init或启动函数中初始化一次,全局调用;
  2. 设置连接池参数:必须通过db.DB()获取底层sql.DB,设置SetMaxOpenConns和SetMaxIdleConns,避免高并发下连接耗尽;
  3. 优先使用条件更新/删除:禁止无条件的Update/Delete,防止误操作全表;
  4. 查询指定字段:使用Select指定需要的字段,避免查询全字段,提升数据库查询性能;
  5. 批量操作优先:插入/更新大量数据时,使用CreateInBatches/批量更新,避免循环单条操作,减少SQL请求次数;
  6. 开启SQL日志:开发环境开启日志(logger.Info),方便调试;生产环境关闭或设置为logger.Error,减少日志开销;
  7. 使用软删除:默认开启软删除(模型加DeletedAt),防止误删除数据,便于数据恢复;
  8. 关联查询用Preload:避免N+1查询问题,提升关联查询性能;
  9. 复杂逻辑用原生SQL:ORM无法覆盖所有复杂场景,此时直接使用Raw/Exec执行原生SQL,更高效;
  10. 事务包裹原子操作:涉及多表修改/多次数据库操作的原子逻辑,必须用事务包裹,保证数据一致性。

六、总结

GORM v2是Go语言生态中功能完善、易用性高的ORM框架,核心优势如下:

  1. 支持主流数据库(MySQL/PostgreSQL/SQLite/SQL Server),解耦核心框架与驱动,扩展方便;
  2. 优雅的链式调用API,大幅降低数据库操作的代码量,提升开发效率;
  3. 内置自动迁移、软删除、事务管理、关联查询、批量操作等核心能力,满足企业级开发需求;
  4. 支持原生SQL执行,兼顾ORM的便捷性和原生SQL的灵活性;
  5. 并发安全的*gorm.DB,适合高并发Go项目。

开发中需重点掌握模型定义(Tag配置)、核心CURD、事务管理、关联查询四大核心能力,同时遵循最佳实践(连接池、批量操作、条件操作等),才能充分发挥GORM的优势,打造高效、稳定的Go数据库应用。

|(注:文档部分内容可能由 AI 生成)


MySQL 和 Redis 的配置文件格式选择是一个常见的问题。以下是对 cnf 格式和 YAML 格式的详细解释:

### cnf 格式配置文件的用途

**1. 原生支持**

- **MySQL**:my.cnf 是 MySQL 的官方默认配置文件格式,MySQL 服务启动时会自动读取

- **Redis**:redis.conf 是 Redis 的官方默认配置文件格式,Redis 服务启动时会自动读取

**2. 格式特点**

- 采用 INI 风格的配置格式,使用 `[section]` 划分不同配置区域

- 配置项采用 `key = value` 的形式,简洁明了

- 支持注释(以 `#` 开头)

- 是数据库和缓存服务的标准配置格式,被广泛使用

**3. 适用场景**

- **直接运行服务**:当直接在服务器上安装和运行 MySQL/Redis 时,使用 cnf 格式的配置文件

- **容器化部署**:在 Docker 容器中运行时,通常通过挂载 cnf 配置文件来覆盖默认配置

- **服务启动参数**:可以通过 `--defaults-file` 参数指定配置文件路径

### YAML 格式配置文件的用途

**1. 编排工具支持**

- **Docker Compose**:使用 docker-compose.yml 来定义和运行多容器 Docker 应用

- **Kubernetes**:使用 YAML 文件来定义 Pod、Service、Deployment 等资源

**2. 格式特点**

- 采用缩进的层次结构,更具可读性

- 支持列表、嵌套对象等复杂数据结构

- 配置更加结构化,适合定义多组件的关系

**3. 适用场景**

- **容器编排**:在使用 Docker Compose 或 Kubernetes 时,使用 YAML 文件定义服务配置

- **应用配置管理**:作为应用程序的配置文件,管理多个服务的配置

- **配置自动化**:便于版本控制和配置管理工具处理

### 两种格式的关系和使用建议

**1. 各司其职**

- **cnf 格式**:负责服务内部的具体配置参数

- **YAML 格式**:负责服务的编排和部署配置

**2. 在 Docker 环境中的使用**

- **docker-compose.yml**:定义服务的部署参数(端口映射、 volumes、环境变量等)

- **my.cnf/redis.conf**:通过 volumes 挂载到容器中,配置服务的具体参数

**3. 最佳实践**

- **保持分离**:将部署配置(YAML)与服务内部配置(cnf)分开管理

- **版本控制**:将两种配置文件都纳入版本控制系统

- **环境隔离**:为不同环境(开发、测试、生产)准备不同的配置文件

### 总结

- **cnf 格式**:是 MySQL 和 Redis 的原生配置格式,专注于服务内部的详细参数配置

- **YAML 格式**:是容器编排和配置管理的标准格式,专注于服务的部署和管理

- **两者配合使用**:在现代容器化环境中,通常同时使用这两种格式,各司其职,共同构成完整的配置体系

因此,即使在使用 YAML 进行容器编排的情况下,cnf 格式的配置文件仍然是必不可少的,因为它负责定义服务的具体运行参数。

内容反馈

发现错误或想补充内容?

GoClub Pro 是静态知识库,评论功能不再加载第三方脚本。你可以在 GitHub 仓库提交 Issue,反馈会直接进入项目协作流程。

提交 GitHub 反馈