Gorm使用规范&&最佳实践1/4 |Go主题月

3,621 阅读2分钟

gorm使用规范和最佳实践,仅做参考

包/函数管理

model层下,对于每一张表建议使用一个文件进行管理。例如student表:

// student.go
type student struct {
    id   uint
    name string 
    ...
}

func ...{ // student表对应的方法
}

对于方法的管理建议使用controller进行管理起来:

type StudentCtl struct {}

func (s * StudentCtl) QueryStudent(){
    ...
}

每一个文件中维护一个默认的私有controller,将获取controller的方法暴露给其他包/文件:

var sc StudentCtl
func GetStudentCtl() *StudentCtl {
  return &sc
}

为什么需要Ctl?Ctl方便对表内方法进行管理,清晰的告诉其调用者,这是一个model层的方法,是数据库操作相关方法,需要考虑事务等数据库操作相关的问题,而不是一个普通函数。 Ctl也有助于在考虑实现功能时进行方法的解耦。

数据库连接

Peter Bourgon在[Translation]现代GO的一些理论中认为不应当产生包级别变量,而是应该将诸如数据库连接变量传递,事实上这也是事务控制所必须的方法。 个人建议在model层/包下维护全局变量db,直接使用db进行查询,但是禁止对db进行赋值(数据库连接一旦被赋值可能造成非常严重的后果,例如db = nil):

// model 包下
var db *gorm.DB
func initDB (){
    db,err = gorm.Open()
    ...
}

对于特定数据库连接,例如事务控制tx,可以对其进行返回来避免数据库连接的覆盖,以及在需要事务的时候进行事务控制:

func getDB(dbs ...*gorm.DB) *gorm.DB {
  if len(dbs) > 0 {
    return dbs[0]
  }
  return db
}

func (ctl *StudentCtl) QueryStudent(dbs... *gorm.DB){
    tx := getDB(dbs...)
    ...
}

命名规范

建议强制使用TableName来指定表和结构体的映射关系:

func (Users) TableName() string {
  return "users"
}

对于查询类方法,使用QueryXXX;对于更新类方法,使用UpdateXXX;对于删除类方法,使用DeleteXXX;创建类方法使用CreateXXX:

func (ctl *StudnetCtl)QueryStudent(dbs... *gorm.DB){
    ...
}

func (ctl *StudnetCtl)CreateStudent(dbs... *gorm.DB){
    ...
}

func (ctl *StudnetCtl)UpdateStudent(map[string]interface{},dbs... *gorm.DB){
    ...
}

func (ctl *StudnetCtl)DeleteStudent(dbs...*gorm.DB){
    ... 
}