Go三件套使用 1| 青训营笔记

74 阅读3分钟

这是我参与「第五届青训营 」伴学笔记创作活动的第 13 天

三件套简介

Gorm: ORM框架

Kitex: Golang微服务的RPC框架,高性能,强可扩展性的,支持多协议,

Hertz: HTTP框架,具有高易用性,高性能,高扩展性

Gorm的CRUD

type Product struct{
	Code string
	Price uint
}//定义结构

funcm (p Product) TableName() string{
	return "product"
}//返回表名

func main(){
	db, err:=gorm.Open(
	mysql.Open(dsn: "user:pass@tcp(127.0.0.1:3306)/dbname?charset=utf8mb4&parseTime=True&loc=local"),
	&gorm.Config{}
	)//初始化mysql的数据库连接
	if err != nil{
        panic("failed to connect database")
	}
    db.Create(&Product{Code:"D42", Price:100})//创建数据
    var product Product
    db.First(&product, 1)//默认基于整形主键查找
    db.Model(&product, "code=?","D42")//查询code为D42的记录,first只能查单个记录,find可以多个
    db.Model(&product).Update("Price", 200)//更新单列数据
    db.Model(&product).Updates(Product{Price:200, Code:"F42"})//更新多列
    db.Model(&product).Updates(map[string]interface{}{"Price":200, "Code": "F42"})
    db.Delete(&product, 1)//删除
}
  • 在没有定义表名称时会使用结构体的蛇形负数作为表名称,字段名的蛇形作为列名。
  • 使用CreateAt,UpdateAt字段作为创建和更新时间

连接数据库

Gorm以驱动的方式支持数据库,包括MySQL, SQLServer,PostgreSQL等。DSN包含了连接数据库的信息。

创建数据

type Product struct{
code string `gorm:"column:co"`
name string `gorm:"default:"`
}

p := &Product{Code:"D42"}
db.Create(p)
db.Clauses(clause.OnConflict{DoNothing:true}).Create(&p)
  • 通过gorm的标签定义列名称,通过default标签定义默认值,通过primarykey设置主键
  • 创建数据可能出现唯一索引冲突,使用clause.OnConflict来避免数据冲突

查询数据

u:=&User{}
db.First(u)
db.Where("age>10").find(&users)//where语句还支持传递结构体和map
  • First查不到数据会返回ErrRecordNotFound导致程序出错, 使用Find查询多条数据,查询不到数据不会返回错误

  • 使用结构体注意只会查询非0值字段,所以值为空,是不用于构建查询的,这时候使用map,或gorm提供的select实现。

更新数据

db.Model(&User{ID:111})..Updates(map[string]interface{}{"name":"hello", "age":18,"actived":false}) 
  • 用model设置表名,使用结构体更新多个列。

删除数据

物理删除

db.Delete(&Usr{},10) 

软删除

type User struct{
    ID int64
    Age int64 
    Deleted gorm.DeletedAt
}
u:=User{ID:111}
db.Delete(&u)
  • gorm.DeleteAt来实现软删除,拥有软删除能力的Model调用delete时,记录不会被从数据库中真正删除,但gorm会将deletedAt置为当前时间,而且不能通过正常查询方法找到该记录,使用Unscoped可以查到被软删的数据

  • 动词语句如create update会直接调用sql语句,所以在create后面跟where是不会生效的。where是用来拼凑SQL的,查询结果需要暂时用result来保留。

Gorm事务

  • 手动执行提供Begin Commit Rollback等方法使用事务,而自动执行使用transacation。
tx:=db.Begin()//固化一个链接而不是使用连接池的连接,开启事务,
if err = tx.Create(&User(Name:"name")).Error;err!=nil{
	tx.Rollback()
	return 
}
if err =tx.Create(&User{Name:"name1"}).Error;err!=nil{
tx.Rollback()//忘记rollback可能导致链接泄漏
return
}
tx.Commit
//transaction自动提交事务

db.Transaction(func(tx * gorm.DB) err {
	 if err = tx.Create(&User{Name:"hi"}).Error; err != nil{
	 return err
	 }
	 if err = tx.Create(&User{Name:"u"}).Error; err != nil{
	 return err
	 }
	return nil
);

hook

func (u *User) BeforeCreate(tx *gorm.DB) (err error)
func (u *User) AfterCreate(tx * gorm.DB) (err error)
  • gorm提供了crud的hook功能, hook是在创建,查询等操作之前和之后调用的函数,如果任何hook返回错误,gorm将停止后续的操作并回滚事务。

  • gorm会开启一个默认事务,hook会包含在该事务内。

性能提高

  • PrepareStmt缓存预编译语句可以提高后续调用速度。

  • 写操作,为了确保数据的完整性,GORM会默认封装在事务中,会降低性能。在部分情况下可以SkipDefaultTransaction关闭默认事务,

常用扩展