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
相关推荐
IT_陈寒3 小时前
用了Proxy才发现以前的JavaScript白写了
前端·人工智能·后端
唐青枫3 小时前
别把 ArrayList 当成会自动管理内存的 List:Zig 动态数组从入门到实战
后端
鸿蒙开发3 小时前
我为 HarmonyOS 做了一个统一大模型 SDK:@hmkit/ai 正式开源
后端
猪是念来过倒3 小时前
Semaphore 与 RateLimiter:并发控制双雄详解
后端
掘金者阿豪4 小时前
异构数据同步最怕什么?不是同步慢,而是数据对不上
后端
程序员cxuan5 小时前
Claude 官方的学习教程,太强了。
人工智能·后端·程序员
老孙讲技术5 小时前
把工地遮挡和掉线接进项目部:setMessageCallback 订 alarm 与 deviceStatus
后端·物联网·音视频开发
老孙讲技术5 小时前
关店后有人进门,监控值班群却没响:用 setMessageCallback 订 human,再用 aiHuman 打开人形
后端·物联网·音视频开发
LEE5 小时前
原来 Claude Code 最厉害的工具,一行代码都不写
前端·后端
老孙讲技术5 小时前
把园区几百路摄像头收进值班台账:bindDevice 入账与 listDeviceDetailsByPage 翻页
后端·物联网·音视频开发