HOW - Go 开发入门(四)- ORM 对象关系映射

文章目录

在 HOW - Go 开发入门(一) 我们进行了开发入门的开篇介绍。今天我们主要介绍第 3 步:接数据库(ORM)。

ORM 是什么?

ORM = Object-Relational Mapping(对象关系映射)

  • 核心目标:把数据库表和 Go 的 struct 对象 一一对应
  • 不用写大量 SQL,直接用熟悉的 struct + 方法操作数据库
  • 优势:
    • 简化开发
    • 避免手写重复 SQL
    • 提高可维护性

GORM 简介

GORM 是 Go 生态最流行的 ORM:

  • 支持 MySQL、Postgres、SQLite、SQLServer 等
  • 提供:
    • 自动迁移(自动生成表结构)
    • CRUD 方法
    • 关联关系(One2Many, Many2Many)
    • Hooks(回调:BeforeCreate, AfterUpdate 等)
  • 易用又贴近 Go 风格

初始化数据库连接

go 复制代码
package main

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

func main() {
    dsn := "root:123456@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 {
        panic("failed to connect database")
    }
    _ = db
}

说明:

  • dsn:数据库连接字符串
  • gorm.Open:返回 *gorm.DB 对象,用于操作数据库

定义 Model(结构体)

go 复制代码
type User struct {
    ID   uint   `gorm:"primaryKey"`
    Name string `gorm:"size:100"`
    Age  int
}
  • ID 主键
  • Name 限制长度 100
  • Age 默认 int
  • GORM 会自动根据 struct 创建对应表

自动迁移(创建表)

go 复制代码
db.AutoMigrate(&User{})
  • 自动创建表或修改表结构
  • 推荐在项目启动时调用

CRUD 基本操作

Create

go 复制代码
db.Create(&User{Name: "Tom", Age: 18})
  • 插入一条数据
  • 自动填充 ID

Read

go 复制代码
var user User
db.First(&user, 1)           // 根据主键查
db.Where("name = ?", "Tom").Find(&user) // 条件查询

Update

go 复制代码
db.Model(&user).Update("Age", 20)
db.Model(&user).Updates(User{Name: "Tommy", Age: 21})

Delete

go 复制代码
db.Delete(&user) // 根据主键删除

关联关系(常用)

One2Many

go 复制代码
type Order struct {
    ID     uint
    UserID uint
    Total  float64
}

type User struct {
    ID     uint
    Name   string
    Orders []Order
}
  • GORM 会自动识别 UserID 外键
  • 查用户 + 订单:
go 复制代码
var user User
db.Preload("Orders").First(&user, 1)

Many2Many

go 复制代码
type Role struct {
    ID   uint
    Name string
    Users []User `gorm:"many2many:user_roles;"`
}
  • 自动生成中间表 user_roles

Hooks(回调)

  • BeforeCreate / AfterCreate / BeforeUpdate / AfterDelete
  • 用于做统一日志、验证、缓存等
go 复制代码
func (u *User) BeforeCreate(tx *gorm.DB) (err error) {
    if u.Age < 0 {
        return errors.New("invalid age")
    }
    return nil
}

高级功能

  • 事务
go 复制代码
tx := db.Begin()
if err := tx.Create(&User{Name: "Alice"}).Error; err != nil {
    tx.Rollback()
} else {
    tx.Commit()
}
  • 原生 SQL
go 复制代码
db.Raw("SELECT * FROM users WHERE age > ?", 18).Scan(&users)

Go + GORM 的工程化思路

  1. 每张表定义一个 struct(model)
  2. 提供 CRUD 方法(Repository/Service 层)
  3. 启动时自动迁移表
  4. 对于复杂查询,使用原生 SQL 或 chain 方法
  5. 用 interface 封装数据库操作 → 可替换 MySQL / Postgres / 测试 mock
相关推荐
摸爬滚打的小李16 分钟前
Spring XML + WAR + Tomcat 项目启动
后端
樱花树下的数学喵1 小时前
手写简易 STL string|C++ 字符串底层实现
开发语言·c++
IT_陈寒1 小时前
SpringBoot自动配置的坑,这次终于爬出来了
前端·人工智能·后端
jimy11 小时前
C++ 报错的 qualifiers 的意思
开发语言·c++
RainbowFish1 小时前
# RAG 与智能体记忆:从原理到工程实践 > 一篇给学习者的总结。
后端
苏三说技术2 小时前
为什么越来越多人用Arthas 4 ?
后端
ServBay2 小时前
AI 开发平台出事后,API Key 泄露要怎么办
后端·aigc·ai编程
程序员老申2 小时前
解剖 PDF 底层二进制:一行代码如何抓出假薪资流水的 3 处破绽
后端
JuiceFS2 小时前
从 Meta 的工程实践看 EB 级 AI 存储架构
人工智能·后端
数据库小学妹2 小时前
MySQL NULL陷阱:NOT IN、三值逻辑与NOT EXISTS
数据库·后端·mysql