暂无图片
暂无图片
暂无图片
暂无图片
暂无图片

Go操作数据库与Gorm

Raymond运维 2024-01-03
22

关注「Raymond运维」公众号,并设为「星标,第一时间获取更多运维等文章,不再错过精彩内容。


Go连接MySQL

首先我们来看如何使用Golang连接MySQL

安装所需要的驱动

go get github.com/go-sql-driver/mysql

导入所需要使用的包

import (
    "database/sql"
    "fmt"
    _ "github.com/go-sql-driver/mysql"
)

连接MySQL需要使用的语句

func main() {
    //"用户名:密码@[连接方式](主机名:端口号)/数据库名"
    db, _ := sql.Open("mysql""root:pwd@(localhost)/database"// 设置连接数据库的参数
    defer db.Close()                                            //关闭数据库
    err := db.Ping()                                            //连接数据库
    if err != nil {
        fmt.Println("Open database fail !")                             //连接失败
        return
    }
    fmt.Println("Connection succdess !")                             //连接成功
}

案例演示

建表

先在MySQL中创建一个名为 test
 的数据库,在此数据库中创建一个 user
 表,包含五个字段id, name, age, sex, phone
 ,并插入几条数据,推荐使用Navicat等图形化管理工具,不用麻烦地在 MySQL 命令行写SQL语句。表如下:



连接MySQL

将数据库的相关配置写成常量,创建  InitDB
 函数用于连接数据库,创建Query
 函数用于查询数据,全部代码如下:

package main

import (
 "database/sql"
 "fmt"
 _ "github.com/go-sql-driver/mysql"
 "github.com/pkg/errors"
 "strings"
)

// 数据库配置
const (
 userName = "root"
 password = "******"
 ip       = "127.0.0.1"
 port     = "3306"
 dbName   = "test"
)

// Db数据库连接池
var DB *sql.DB

type User struct {
 id    int64
 name  string
 age   int8
 sex   int8
 phone string
}

// 注意方法名大写,就是public
func InitDB() {
 //构建连接:"用户名:密码@tcp(IP:端口)/数据库?charset=utf8"
 path := strings.Join([]string{userName, ":", password, "@tcp(", ip, ":", port, ")/", dbName, "?charset=utf8"}, "")
 //打开数据库,前者是驱动名,所以要导入: _ "github.com/go-sql-driver/mysql"
 DB, _ = sql.Open("mysql", path)
 //设置数据库最大连接数
 DB.SetConnMaxLifetime(100)
 //设置上数据库最大闲置连接数
 DB.SetMaxIdleConns(10)
 //验证连接
 if err := DB.Ping(); err != nil {
  fmt.Println("open database fail !")
  return
 }
 fmt.Println("connnection success !")
}

// 查询操作
func Query() {
 var user User
 rows, e := DB.Query("select * from user where id in (1,2,3)")
 if e == nil {
  errors.New("query incur error")
 }
 for rows.Next() {
  e := rows.Scan(&user.sex, &user.phone, &user.name, &user.id, &user.age)
  if e != nil {
   fmt.Println(user.sex, user.phone, user.name, user.id, user.age)
  }
 }
 rows.Close()
}

func main() {
 InitDB()
 Query()
 defer DB.Close()
}

以上是使用Golang连接MySQL数据库的基础方法,接下来我们看Gorm是如何连接MySQL。

Gorm

什么是ORM

对象关系映射 :Object-Relational Mapping,用于在关系数据库和面向对象编程语言的堆之间转换数据。这样就创建了一个虚拟的对象数据库,可以从编程语言内部使用。

ORM提供了自动支持,用于将元组映射到对象并返回,同时考虑所有这些差异。问题的核心在于将对象的逻辑表示转换为能够存储在数据库中的原子形式,同时保留对象的属性和它们之间的关系,以便在需要时可以重新加载为对象。如果实现了这种存储和检索功能,则称这些对象是持久的。

优点

  • 提高开发效率,减少开发成本
  • 使开发更加面向对象
  • 可移植性
  • 可以轻松引入额外功能,如数据缓存。
  • 加快开发速度 - 消除了重复的SQL代码的需要。
  • 减少开发时间、成本
  • 克服特定于供应商的SQL差异 - ORM知道如何编写特定于供应商的SQL

缺点

  • 在学习使用ORM时会损失生产力
  • 失去了对代码实际执行内容的理解 - 使用SQL时,开发人员更能控制
  • ORM有变慢的倾向
  • ORM无法与复杂查询的SQL查询竞争

Grom介绍

Gorm是一种功能强大且对开发人员友好的ORM库,支持主流的数据库。

GORM 官方支持的数据库类型有:MySQL, PostgreSQL, SQLite, SQL Server 和 TiDB

安装

go get -u gorm.io/gorm
go get -u gorm.io/driver/mysql

连接MySQL

和基本的连接方法区别不大

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

func main() {
  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{})
}

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

GORM MODEL 定义

在使用ORM工具时,我们需要在代码中定义模型(Models)与数据库中的数据表进行映射,模型是标准的 struct,由 Go 的基本数据类型、实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成

约定

GORM 倾向于约定优于配置 默认情况下,GORM 使用 ID
 作为主键,使用结构体名的 蛇形复数
 作为表名,字段名的 蛇形
 作为列名,并使用 CreatedAt
UpdatedAt
 字段追踪创建、更新时间

如果您遵循 GORM 的约定,您就可以少写的配置、代码。如果约定不符合您的实际要求,GORM 允许你配置它们

gorm.Model

GORM 定义一个 gorm.Model
 结构体,其包括字段 ID
CreatedAt
UpdatedAt
DeletedAt

// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

您也可以将其嵌入到自己的结构体当中,如下:

type User struct {
  gorm.Model
  Name string
}
// 等效于
type User struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
  Name string
}

当然您也可以完全使用自己定义的结构体,不一定需要使用它的 model

原文链接:https://mp.weixin.qq.com/s/gqzj6Rv33HKmqmviWetdtw













WeChat group


为方便大家更好的交流运维等相关技术问题,特创建了微信交流群。需要加群的小伙伴们在关注微信公众号后,点击底部菜单关于联系我,即可获取加群方式。


博客

Blog

CSDN博客

掘金博客

长按识别二维码访问博客网站,查看更多优质原创运维等文章。

文章转载自Raymond运维,如果涉嫌侵权,请发送邮件至:contact@modb.pro进行举报,并提供相关证据,一经查实,墨天轮将立刻删除相关内容。

评论