开源 Golang 微服务入门三:ORM 框架 GORM| 青训营笔记

本文涉及的产品
云数据库 RDS MySQL,集群系列 2核4GB
推荐场景:
搭建个人博客
RDS MySQL Serverless 基础系列,0.5-2RCU 50GB
云数据库 RDS MySQL,高可用系列 2核4GB
简介: GORM 是面向 Golang 语言的一种 ORM(持久层)框架,支持多种数据库的接入,此框架弱化了开发者对于 SQL 语言的掌握程度,使用提供的 API 进行底层数据库的访问。使用提供的 API 进

👏 Hi! 我是 Yumuing,一个技术的敲钟人

👨‍💻 每天分享技术文章,永远做技术的朝拜者

📚 欢迎关注我的博客:Yumuing's blog

前言

前两篇笔记分别介绍了 Golang 微服务 HTTP 框架 Hertz 和 Golang 微服务 RPC 框架 Kitex,本文将要介绍面向ORM(持久层)框架 GORM。

官方文档

GORM 是面向 Golang 语言的一种 ORM(持久层)框架,支持多种数据库的接入,例如 MySQL,PostgreSQL,SQLite,SQL Server,Clickhouse。此框架的特点,弱化了开发者对于 SQL 语言的掌握程度,使用提供的 API 进行底层数据库的访问。

GORM 官方支持的数据库类型有: MySQL, PostgreSQL, SQlite, SQL Server。

作者是中国人,中文文档齐全,对开发者友好,支持主流数据库。

特点:

  • 全功能ORM;
  • 关联(包含一个,包含多个,属于,多对多,多种包含);
  • Callbacks(创建/保存/更新/删除/查找之前/之后);
  • 预加载;
  • 事务
  • 复合主键
  • SQL Builder
  • 自动迁移
  • 日志
  • 可扩展,编写基于GORM回调的插件
  • 每个功能都有测试
  • 开发人员友好

快速启动

安装与连接:

go get github.com/jinzhu/gorm
AI 代码解读

连接 MySQL 数据库:

package main

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

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{})
    db, err := gorm.Open(mysql.New(mysql.Config{
   
   
        DSN:                       "root:123456@tcp(192.168.168.101:3306)/gorm?charset=utf8&parseTime=True&loc=Local", // DSN data source name
        DefaultStringSize:         256,                                                                                // string 类型字段的默认长度
        DisableDatetimePrecision:  true,                                                                               // 禁用 datetime 精度,MySQL 5.6 之前的数据库不支持
        DontSupportRenameIndex:    true,                                                                               // 重命名索引时采用删除并新建的方式,MySQL 5.7 之前的数据库和 MariaDB 不支持重命名索引
        DontSupportRenameColumn:   true,                                                                               // 用 `change` 重命名列,MySQL 8 之前的数据库和 MariaDB 不支持重命名列
        SkipInitializeWithVersion: false,                                                                              // 根据当前 MySQL 版本自动配置
    }), &gorm.Config{
   
   })
    if err != nil {
   
   
        panic("failed to connect database")
    }
    // ----------------------------数据库连接池----------------------------
    sqlDB, err := db.DB()
    // SetMaxIdleConns 设置空闲连接池中连接的最大数量
    sqlDB.SetMaxIdleConns(10)
    // SetMaxOpenConns 设置打开数据库连接的最大数量。
    sqlDB.SetMaxOpenConns(100)
    // SetConnMaxLifetime 设置了连接可复用的最大时间。
    sqlDB.SetConnMaxLifetime(time.Hour)
    fmt.Println("success to link mysql")
    select {
   
   }
}
AI 代码解读

注意: 想要正确的处理 time.Time ,您需要带上 parseTime 参数, (更多参数) 要支持完整的 UTF-8 编码,您需要将 charset=utf8 更改为 charset=utf8mb4

MySQL 高级配置:

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

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{
   
   })
AI 代码解读

GORM 允许通过一个现有的数据库连接来初始化 gorm.DB

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

sqlDB, err := sql.Open("mysql", "mydb_dsn")
gormDB, err := gorm.Open(mysql.New(mysql.Config{
   
   
  Conn: sqlDB,
}), &gorm.Config{
   
   })
AI 代码解读

表数据操作:增删改查

package main

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

type User struct {
   
   
Id   int
Name string
Age  int
Addr string
Pic  string
}

func main() {
   
   
dsn := "root:root123\@tcp(127.0.0.1:3306)/test\_gorm?charset=utf8mb4\&parseTime=True\&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), \&gorm.Config{
   
   })
if err != nil {
   
   
panic(err)
}
// 自动迁移
db.Set("gorm:table\_options", "ENGINE=InnoDB").AutoMigrate(\&User{
   
   })

    // 增
    db.Create(&User{
   
   
        Name: "张三",
        Age:  18,
        Addr: "北京市",
        Pic:  "/static/img.png",
    })

    // 查
    var user User
    db.First(&user)
    fmt.Println(user) // {1 张三 18 北京市 /static/img.png}

    // 改
    user.Name = "lisi"
    db.Save(&user)
    fmt.Println(user) // {1 lisi 18 北京市 /static/img.png}

    // 删
    db.Delete(&user)

}
AI 代码解读

模型定义:

模型名和表名的映射关系

规则:

  • 第一个大写字母变为小写;
  • 遇到其他大写字母变为小写并且在前面加下划线;
  • 连着的几个大写字母,只有第一个遵循上面的两条规则,其他的大写字母转为小写,不加下划线,遇到小写,前面的第一个大写字母变小写并加下划线;
  • 复数形式;

举例:

  • User => users 首字母小写,复数
  • UserInfo => user_infos
  • DBUserInfo => db_user_infos
  • DBXXXXUserInfo => dbxxxx_user_infos

结构体字段名和列名的对应规则

规则 * 列名是字段名的蛇形小写\
举例

  • Name --> name
  • CreatedTime --> create_time\
    可以通过gorm标签指定列名,AnimalId int64 gorm:"column:beast_id"

gorm.Model

基本模型定义gorm.Model,包括字段 ID,CreatedAt,UpdatedAt,DeletedAt

参数说明:

  • ID:主键自增长;
  • CreatedAt:用于存储记录的创建时间;
  • UpdatedAt:用于存储记录的修改时间;
  • DeletedAt:用于存储记录的删除时间;

只需要在自己的模型中指定gorm.Model匿名字段,即可使用上面的四个字段

gorm.Model.go
package gorm

import "time"

// Model a basic GoLang struct which includes the following fields: ID, CreatedAt, UpdatedAt, DeletedAt
// It may be embedded into your model or you may build your own model without it
//    type User struct {
   
   
//      gorm.Model
//    }
type Model struct {
   
   
ID        uint `gorm:"primarykey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt DeletedAt `gorm:"index"`
}


// 添加字段 `ID`, `CreatedAt`, `UpdatedAt`, `DeletedAt`
type User struct {
   
   
gorm.Model
Name string
}
AI 代码解读

高级选项

结构体标签gorm的使用:

type User struct {
   
   
Name string `gorm:"<-:create"` // 允许读和创建
Name string `gorm:"<-:update"` // 允许读和更新
Name string `gorm:"<-"`        // 允许读和写(创建和更新)
Name string `gorm:"<-:false"`  // 允许读,禁止写
Name string `gorm:"->"`        // 只读(除非有自定义配置,否则禁止写)
Name string `gorm:"->;<-:create"` // 允许读和写
Name string `gorm:"->:false;<-:create"` // 仅创建(禁止从 db 读)
Name string `gorm:"-"`  // 读写操作均会忽略该字段
}
AI 代码解读

创建/更新时间追踪(纳秒、毫秒、秒、Time):

GORM 约定使用 CreatedAt、UpdatedAt 追踪创建/更新时间。如果您定义了这种字段,GORM 在创建、更新时会自动填充 当前时间

要使用不同名称的字段,您可以配置 autoCreateTim、autoUpdateTim 标签
如果您想要保存 UNIX(毫/纳)秒时间戳,而不是 time,您只需简单地将 time.Time 修改为 int 即可

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

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag: tag 名大小写不敏感,但建议使用 camelCase 风格,也就是驼峰 camelCase 命名风格。多个属性值之间用分号分隔(英文的;):gorm:"size:64;not null"

image.png

案例

package main

import (
"gorm.io/driver/mysql"
"gorm.io/gorm"
"gorm.io/gorm/logger"
"log"
"os"
"time"
)

type User struct {
   
   
UserId uint `gorm:"primaryKey"`
Name string `gorm:"column:user_name;type:varchar(60)"`
Gender uint `gorm:"index"`
}

func main() {
   
   
// 日志配置
newLogger := logger.New(
log.New(os.Stdout, "\r\n", log.LstdFlags), // io writer(日志输出的目标,前缀和日志包含的内容——译者注)
logger.Config{
   
   
SlowThreshold:             time.Second, // 慢 SQL 阈值
LogLevel:                  logger.Info, // 日志级别为info
IgnoreRecordNotFoundError: true,        // 忽略ErrRecordNotFound(记录未找到)错误
Colorful:                  true,        // 彩色打印
},
)

    dsn := "root:123@tcp(127.0.0.1:3306)/gorm_test?charset=utf8mb4&parseTime=True&loc=Local"
    db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
   
   
        Logger: newLogger,
    })
    if err != nil {
   
   
        panic(err) // 如果数据库不存在会报错
    }
    db.AutoMigrate(&User{
   
   }) 

// 如果表之前存在会修改,但是只会修改之前存在的字段的属性,无法识别删除字段
}
AI 代码解读

总结

本文主要介绍了 GORM 框架的相关基础知识,介绍了常用的接口函数,具体的细节还是需要仔细研究官方文档。这三个框架的学习都可以看出官方文档的重要性,同时学习框架还是要多上手练习才行。

求点赞转发

相关实践学习
如何快速连接云数据库RDS MySQL
本场景介绍如何通过阿里云数据管理服务DMS快速连接云数据库RDS MySQL,然后进行数据表的CRUD操作。
全面了解阿里云能为你做什么
阿里云在全球各地部署高效节能的绿色数据中心,利用清洁计算为万物互联的新世界提供源源不断的能源动力,目前开服的区域包括中国(华北、华东、华南、香港)、新加坡、美国(美东、美西)、欧洲、中东、澳大利亚、日本。目前阿里云的产品涵盖弹性计算、数据库、存储与CDN、分析与搜索、云通信、网络、管理与监控、应用服务、互联网中间件、移动服务、视频服务等。通过本课程,来了解阿里云能够为你的业务带来哪些帮助 &nbsp; &nbsp; 相关的阿里云产品:云服务器ECS 云服务器 ECS(Elastic Compute Service)是一种弹性可伸缩的计算服务,助您降低 IT 成本,提升运维效率,使您更专注于核心业务创新。产品详情: https://www.aliyun.com/product/ecs
目录
相关文章
Eino:字节跳动开源基于Golang的AI应用开发框架,组件化设计助力构建AI应用
Eino 是字节跳动开源的大模型应用开发框架,帮助开发者高效构建基于大模型的 AI 应用。支持组件化设计、流式处理和可视化开发工具。
325 27
|
6月前
|
ServiceStack:不仅仅是一个高性能Web API和微服务框架,更是一站式解决方案——深入解析其多协议支持及简便开发流程,带您体验前所未有的.NET开发效率革命
【10月更文挑战第9天】ServiceStack 是一个高性能的 Web API 和微服务框架,支持 JSON、XML、CSV 等多种数据格式。它简化了 .NET 应用的开发流程,提供了直观的 RESTful 服务构建方式。ServiceStack 支持高并发请求和复杂业务逻辑,安装简单,通过 NuGet 包管理器即可快速集成。示例代码展示了如何创建一个返回当前日期的简单服务,包括定义请求和响应 DTO、实现服务逻辑、配置路由和宿主。ServiceStack 还支持 WebSocket、SignalR 等实时通信协议,具备自动验证、自动过滤器等丰富功能,适合快速搭建高性能、可扩展的服务端应用。
331 3
Dubbo学习圣经:从入门到精通 Dubbo3.0 + SpringCloud Alibaba 微服务基础框架
尼恩团队的15大技术圣经,旨在帮助开发者系统化、体系化地掌握核心技术,提升技术实力,从而在面试和工作中脱颖而出。本文介绍了如何使用Dubbo3.0与Spring Cloud Gateway进行整合,解决传统Dubbo架构缺乏HTTP入口的问题,实现高性能的微服务网关。
如何选择合适的微服务框架
如何选择合适的微服务框架
90 0
微服务框架Dubbo环境部署实战
微服务框架Dubbo环境部署的实战指南,涵盖了Dubbo的概述、服务部署、以及Dubbo web管理页面的部署,旨在指导读者如何搭建和使用Dubbo框架。
517 17
微服务框架Dubbo环境部署实战
用 Quarkus 框架优化 Java 微服务架构的设计与实现
Quarkus 是专为 GraalVM 和 OpenJDK HotSpot 设计的 Kubernetes Native Java 框架,提供快速启动、低内存占用及高效开发体验,显著优化了 Java 在微服务架构中的表现。它采用提前编译和懒加载技术实现毫秒级启动,通过优化类加载机制降低内存消耗,并支持多种技术和框架集成,如 Kubernetes、Docker 及 Eclipse MicroProfile,助力开发者轻松构建强大微服务应用。例如,在电商场景中,可利用 Quarkus 快速搭建商品管理和订单管理等微服务,提升系统响应速度与稳定性。
193 5
|
6月前
|
【Golang入门】简介与基本语法学习
Golang语言入门教程,介绍了Go语言的简介、基本语法、程序结构、变量和常量、控制结构、函数、并发编程、接口和类型、导入包、作用域以及错误处理等关键概念,为初学者提供了一个全面的学习起点。
175 0
从零到微服务专家:用Micronaut框架轻松构建未来架构
【9月更文挑战第5天】在现代软件开发中,微服务架构因提升应用的可伸缩性和灵活性而广受欢迎。Micronaut 是一个轻量级的 Java 框架,适合构建微服务。本文介绍如何从零开始使用 Micronaut 搭建微服务架构,包括设置开发环境、创建 Maven 项目并添加 Micronaut 依赖,编写主类启动应用,以及添加控制器处理 HTTP 请求。通过示例代码展示如何实现简单的 “Hello, World!” 功能,并介绍如何通过添加更多依赖来扩展应用功能,如数据访问、验证和安全性等。Micronaut 的强大和灵活性使你能够快速构建复杂的微服务系统。
255 5
随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架
【9月更文挑战第6天】随着微服务架构的兴起,Spring Boot凭借其快速开发和易部署的特点,成为构建RESTful API的首选框架。Nginx作为高性能的HTTP反向代理服务器,常用于前端负载均衡,提升应用的可用性和响应速度。本文详细介绍如何通过合理配置实现Spring Boot与Nginx的高效协同工作,包括负载均衡策略、静态资源缓存、数据压缩传输及Spring Boot内部优化(如线程池配置、缓存策略等)。通过这些方法,开发者可以显著提升系统的整体性能,打造高性能、高可用的Web应用。
104 2
Micronaut对决Spring Boot:谁是微服务领域的王者?揭秘两者优劣,选对框架至关重要!
【9月更文挑战第5天】近年来,微服务架构备受关注,Micronaut和Spring Boot成为热门选择。Micronaut由OCI开发,基于注解的依赖注入,内置多种特性,轻量级且启动迅速;Spring Boot则简化了Spring应用开发,拥有丰富的生态支持。选择框架需考虑项目需求、团队经验、性能要求及社区支持等因素。希望本文能帮助您选择合适的微服务框架,助力您的软件开发项目取得成功!
330 2

热门文章

最新文章