Golang 连接数据库 | 青训营

63 阅读4分钟

数据库

数据是现代应用程序最宝贵的财产,而数据库(database)是管理、持久化保存数据的不可或缺的组件。数据库是一个存放数据的仓库,这个仓库是按照一定的数据结构(数据结构是指数据的组织形式或数据之间的联系)来组织、存储的,我们可以通过数据库提供的多种方法来管理数据库里的数据。数据库主要有关系型和非关系型数据库。

对数据库编程是几乎任何编程语言都有提供的基础功能模块,无论是编程语言内置的支持,还是通过外部库来实现,Golang也不例外;当然啦,不同编程语言提供的数据库编程API是不尽相同的,而且需要支持的数据库也是多种多样,如常用的 MySQLSQLServer,Postgres等数据库。

在编程中我们常做的操作是 CRUD

  • CCreate,代表新建或向数据库插入新记录
  • RRead, 从数据库中检索记录
  • UUpdate,改变数据库中记录的内容
  • DDelete,从数据库中删除记录。

Golang 连接数据库

Golang 提供了多个能实现 CRUD 操作的库,有内置的 low-level 的标准库 database/sql,还有功能丰富的 high-level 的第三方库 GORMsqlxsqlc 等。

database/sql 可以通过官方文档查看使用方法,它运行速度快,代码编写起来简单,但缺点是必须手动将SQL字段映射到变量,非常容易出错,如果变量的顺序不匹配,或者忘记将一些参数传递给函数调用,错误就只会在运行时出现。

sqlx 是对标准库 database/sql 的扩展,速度几乎和标准库一样快,使用也非常简单,字段映射是通过查询文本或结构标签完成的,但同样错误只会在运行时捕获。在写作本文时其原 Github 仓库已有一年多没有更新了,所以暂时放弃它。

sqlc 是编写 SQL 查询语句,自动生成对应的 Golang 代码,它有任何错误都会立即捕获,而不需要等到运行时才知道,目前支持 PostgreSQL, MySQL, SQLite

GORM是一个非常完善的ORM框架,支持很多主流数据库,对开发者非常友好,使用广泛,

GORM

接下来介绍下 GORM 的简单使用方法,为了方便,选用 sqlite3 作为数据库。

package main

import (
	"fmt"

	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

type UserInfo struct {
	Id     int `gorm:"primaryKey"`
	Name   string
	Gender string
	Hobby  string
}

func main() {
	db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
	if err != nil {
		panic("failed to connect database")
	}

	// 数据库迁移,如果不存在则新建表,存在判断字段是否一致不一致修改。
	db.AutoMigrate(UserInfo{})

	// Create
	db.Create(&UserInfo{
		Name:   "Simon",
		Gender: "male",
		Hobby:  "Fitness",
	})

	// Read
	var u UserInfo
	// 用来存放结果的结构体,第二个参数,id
	db.First(&u, 1)
	fmt.Println(u.Name)

	// Update
	db.First(&u, 1).Update("hobby", "running")
	fmt.Printf("姓名:%s, 爱好:%s\n", u.Name, u.Hobby)
	db.Model(&u).Update("Name", "Tom")
	fmt.Printf("姓名:%s, 爱好:%s\n", u.Name, u.Hobby)
	// 更新多个字段
	db.Model(&u).Updates(UserInfo{Name: "Alice", Hobby: "Swimming"}) // 仅更新非零值字段
	fmt.Printf("姓名:%s, 爱好:%s\n", u.Name, u.Hobby)

	// Delete - 删除 product
	db.Delete(&u, 1)
}

例子通过迁移的语句 db.AutoMigrate 来创建表。查询(db.First),更新(Update),删除(Delete)中的参数均为结构体的地址。

GORM 进阶

GORM作为ORM框架并没有提供任何辅助代码开发的功能,导致面对较为复杂的数据库表查询场景时,开发者需逐条手写数据表中的列与对应结构体的成员变量,单调且重复的查询功能也需要手动复制,稍不注意就会造成不易察觉的拼写错误。

其实在 Golang 泛型比较弱的情况下,使用【代码生成】依然是解决个性化场景的经典方案,这样绕开了 interface{},我们就可以做更多校验,也省去了断言。GORM 其实也是基于这个思路,推出了自己的【代码生成工具】:Gen。

GORM Gen 可以连接数据库,根据指定的表生成相应的 Golang 模型代码,非常方便,具体操作留待后篇。

参考

database/sql

GORM

juejin.cn/post/713315…