GO框架三件套 | 青训营

67 阅读5分钟

Gorm的基础使用

Gorm的约定(默认)

Gorm使用名为ID的字段默认作为主键

使用结构体的蛇形负数作为表名

字段名的蛇形作为列名

使用CreatedAt、UpdatedAt字段作为创建、更新时间

type Product struct {
	gorm.Model //继承gorm里面的Model模型
	Code       string `gorm:"default:galeone"`
	Price      uint	  `gorm:default:100000`
}

gorm.Model继承了gorm里面的Model模型,这个字段会自带三个字段:创造时间,更新时间,删除时间

type Model struct {
	ID        uint `gorm:"primarykey"`
	CreatedAt time.Time
	UpdatedAt time.Time
	DeletedAt DeletedAt `gorm:"index"`
}

上面还使用了gorm自带的default标签为字段定义默认值

CRUD

First的使用踩坑 使用 First 时,需要注意查询不到数据会返回ErrRecordNotFound。

使用Find查询多条数据,查询不到数据不会返回错误。

使用结构体作为查询条件

当使用结构作为条件查询时,GORM只会查询非零值字段。这意味着如果您的字段值为0、"、false或其他零值,该字段不会被用于构建查询条件,使用Map来构建查询条件。

var product Product
	db.First(&product, 1) //根据主键查找
	fmt.Printf("product1: %v\n", product)

	db.First(&product, "code=?", "D42") //根据字段查找code字段为D42的记录
	fmt.Printf("product2: %v\n", product)

使用Struct更新时,只会更新非零值,如果需要更新零值,就需要使用Map更新或者使用Select选择字段。

db.Model(&Product{Code: "pant"}).Updates(map[string]interface{}{"Code": "cloth", "Price": 250})

GORM提供了gorm.DeletedAt用于帮助用户实现软件删除

拥有软删除能力的 Model调用Delete时,记录不会被从数据库中真正删除。但GORM会将DeletedAt置为当前时间,并且你不能再通过正常的查询方法找到该记录。

使用Unscoped可以查询到被软删的数据

Gorm事务

在GORM中,事务提供了一种机制来确保一系列数据库操作要么全部成功要么全部失败。

Gorm提供了Begin,Commot,Rollback等方法使用于事务

tx := db.Begin() //开始事务
	//在事务中执行一些db操作(从这里开始,应该使用 'tx' 而不是 'db' )
	if err = tx.Create(&Product{Code: "cloth"}).Error; err != nil {
		tx.Rollback()
		return
	}

	//提交事务
	tx.Commit()

在这个示例中,Begin()方法用于开启事务,Rollback()方法用于回滚事务,Commit()方法用于提交事务。如果在事务过程中发生任何错误,可以调用Rollback()方法回滚事务,否则可以调用Commit()方法提交事务。

Gorm也提供了Tansaction方法用于自动提交事务,避免用户漏泄Commit,Rollback。

Gorm Hook

GORM在提供了CURD的Hook 能力。

Hook是在创建、查询、更新、删除等操作之前、之后自动调用的函数。

如果任何Hook返回错误,GORM将停止后续的操作并回滚事务。

GORM提供了多个不同类型的Hooks,每个类型的Hook都对应一个特定的数据库操作。下面是一些常用的Hooks:

  1. BeforeCreate:在创建记录之前触发的Hook。
  2. AfterCreate:在创建记录之后触发的Hook。
  3. BeforeUpdate:在更新记录之前触发的Hook。
  4. AfterUpdate:在更新记录之后触发的Hook。
  5. BeforeDelete:在删除记录之前触发的Hook。
  6. AfterDelete:在删除记录之后触发的Hook。
  7. BeforeQuery:在查询记录之前触发的Hook。
  8. AfterQuery:在查询记录之后触发的Hook。

and so on。。。

例:

func (p *Product) BeforeCreate(tx *gorm.DB) (err error) {
	if p.Price > 1000 {
		return errors.New("can't save invalid data")
	}
	return
}

func (p *Product) AfterCreate(tx *gorm.DB) (err error) {
	return tx.Create(&Email{ID: int64(p.ID), Email: p.Code + "@***.com"}).Error
}

对于写操作(创建、更新、删除),为了确保数据的完整性,GORM会将它们封装在事务内运行。但这会降低性能,你可以使用SkipDefaultTransaction关闭默认事务。

db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{
		SkipDefaultTransaction: true, //关闭默认事务
		PrepareStmt:            true, //缓存预编译语句,都是为了提高性能
	})

Kitex

使用IDL定义服务与接口

如果我们要进行 RPC,就需要知道对方的接口是什么,需要传什么参数,同时也需要知道返回值是什么。这时候,就 需要通过IDL来约定双方的协议,就像在写代码的时候需要调用某个函数,我们需要知道函数签名—样。

  1. 引入依赖:在 Go 项目中,使用 go mod 或者其它依赖管理工具引入 Kitex 的依赖包。你可以在官方的 GitHub 仓库中找到 Kitex 的最新版本和文档。
go install github.com/cloudwego/kitex/tool/cmd/kitex@latest

go install github.com/cloudwego/thriftgo@latest
  1. 定义服务接口:在 Kitex 中,你需要定义服务接口的 IDL(接口定义语言)。Kitex 支持使用 Protocol Buffers 或者 Thrift 进行接口定义。
  2. 实现服务接口:根据定义的服务接口,编写实现逻辑的代码。你可以在代码中实现服务的业务逻辑,通过调用其它微服务或存储与消息队列进行交互。
  3. 配置和启动服务端:编写服务端的代码,并配置服务的监听地址、端口等参数。在启动时,使用 Kitex 提供的 Server 库来启动服务端。
  4. 调用服务端:编写客户端的代码,并使用 Kitex 提供的 Client 库来调用服务端的接口。可以使用代码生成工具根据接口定义生成客户端的代码。
  5. 监控和调试:Kitex 提供了监控和调试功能,可以方便地进行服务的性能分析和问题排查。

Hertz

Hertz和Web的springboot用法很相似,不过多赘述了。