戈朗。重构||图案||任何解决方案

标签 go

问题:有一个表关联键的列表。有必要为每个表实现 CRUD + 一些针对表细节的功能(分页等)。 麻烦:每个表的每个功能实现中都重复了大约50%的代码。 问题:针对语言的具体情况,优化/重构/使用类似代码模式的方法是什么?

示例代码部分

//------------------------------------------------------------------
//  user
//----------------------------------------------------------------------
func (d *Database) UserCreate(email, password, username string, role int) *Answer {
    //variables
    answer := d.initCall("UserCreate")
    user := new(User)
    //check exist user
    if userExist := d.DB.Find(&User{}, &User{Email:email}).Error; userExist == nil {
        answer.AnswerJSON.ErrorAnswer.Message = "[usercreate] user already exist"
        answer.AnswerJSON.Result = nil
        answer.AnswerJSON.Status = false
    } else {

        userinfo := UserInfo{Data:time.Now()}
        session := Session{Data:time.Now()}
        cook := Cook{}

        //make support  tables object
        //userinfo object
        userinfo.Password = password
        userinfo.Username = username
        //cook object
        cook.SessionID = session.ID
        cook.Cookie = d.cookgeneratenew("somesaltforcooksgenerate")
        cook.Status = true
        cook.Lastconnect = time.Now()
        cook.CountConnect += 1

        //user object
        user.Email = email
        user.Session = session
        user.UserInfo = userinfo
        user.Cook = cook
        user.Role = int64(role)

        //make request + //serizlizations to json answer
        if err := d.DB.Create(user).Error; err != nil {
            answer.AnswerJSON.ErrorAnswer.Message = err.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Result = user
            answer.AnswerJSON.Status = true
        }
    }
    d.serilize(answer)
    return answer
}
func (d *Database) UserDelete(userid int64) *Answer {
    answer := d.initCall("UserDelete")
    user := new(User)
    //check exists
    if userExists := d.DB.Find(user, "ID = ?", userid).Error; userExists == nil {
        if userDelete := d.DB.Delete(user).Error; userDelete != nil {
            answer.AnswerJSON.ErrorAnswer.Message = userExists.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Status = true
            answer.AnswerJSON.ErrorAnswer = nil
        }
    } else {
        answer.AnswerJSON.ErrorAnswer.Message = userExists.Error()
        answer.AnswerJSON.Status = false
    }
    d.serilize(answer)
    return answer
}
func (d *Database) UserRead(userid int64) *Answer {
    answer := d.initCall("UserRead")
    user := new(User)
    if userExists := d.DB.Find(user, "ID = ?", userid).Error; userExists != nil {
        answer.AnswerJSON.ErrorAnswer.Message = userExists.Error()
        answer.AnswerJSON.Status = false
    } else {
        if rel := d.DB.Model(user).Related(&user.Session).Error; rel != nil {
            answer.AnswerJSON.Result = nil
            answer.AnswerJSON.ErrorAnswer.Message = rel.Error()
            answer.AnswerJSON.Status = false
        } else if rel = d.DB.Model(user).Related(&user.UserInfo).Error; rel != nil {
            answer.AnswerJSON.Result = nil
            answer.AnswerJSON.ErrorAnswer.Message = rel.Error()
            answer.AnswerJSON.Status = false
        } else if rel = d.DB.Model(user).Related(&user.Cook).Error; rel != nil {
            answer.AnswerJSON.Result = nil
            answer.AnswerJSON.ErrorAnswer.Message = rel.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Result = user
            answer.AnswerJSON.ErrorAnswer = nil
            answer.AnswerJSON.Status = true
        }
    }
    d.serilize(answer)
    return answer
}
func (d *Database) UserReadAll() *Answer {
    answer := d.initCall("UserReadAll")
    users := []User{}

    if usersGet := d.DB.Find(&users).Error; usersGet != nil {
        answer.AnswerJSON.ErrorAnswer.Message = usersGet.Error()
        answer.AnswerJSON.Status = false
    } else {
        for _, user := range users {
            d.DB.Model(user).Related(&user.Session)
            d.DB.Model(user).Related(&user.UserInfo)
            d.DB.Model(user).Related(&user.Cook)
        }
        answer.AnswerJSON.Result = users
        answer.AnswerJSON.ErrorAnswer = nil
        answer.AnswerJSON.Status = true
    }
    d.serilize(answer)
    return answer
}
func (d *Database) UserUpdate(userid int64, uu *UserUpdateStruct) *Answer {
    answer := d.initCall("UserUpdate")
    user := new(User)

    if userExists := d.DB.Find(user, "ID = ?", userid).Error; userExists != nil {
        answer.AnswerJSON.ErrorAnswer.Message = userExists.Error()
        answer.AnswerJSON.Status = false
    } else {
        //get relevating struct info
        d.DB.Model(user).Related(&user.Session)
        d.DB.Model(user).Related(&user.UserInfo)
        d.DB.Model(user).Related(&user.Cook)

        //update columns
        if uu.Email != "" {
            user.Email = uu.Email
        }
        if uu.Avatar > 0 {
            user.UserInfo.Avatar = uu.Avatar
        }
        if uu.Birthday != "" {
            user.UserInfo.Birthday = uu.Birthday
        }
        if uu.Location != "" {
            user.UserInfo.Location = uu.Location
        }
        if uu.Male != "" {
            user.UserInfo.Male = uu.Male
        }
        if uu.Password != "" {
            user.UserInfo.Password = uu.Password
        }
        if uu.Role > 0 {
            if roleErr := d.DB.Find(&Role{}).Error; roleErr != nil {
                //role not found
                fmt.Printf("[userupdate] role not found `%d`\n", uu.Role)
            } else {
                user.Role = uu.Role
            }
        }

        //update
        if errUpdate := d.DB.Save(user).Error; errUpdate != nil {
            answer.AnswerJSON.ErrorAnswer.Message = errUpdate.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Result = user
            answer.AnswerJSON.ErrorAnswer = nil
            answer.AnswerJSON.Status = true
        }
    }
    d.serilize(answer)
    return answer
}
func (d *Database) UserPaginate(page, countPage int) *Answer {
    answer := d.initCall("UserPaginate")
    result := []*User{}
    if errPag := d.DB.Limit(countPage).Offset((page * countPage) - countPage).Find(&result).Error; errPag != nil {
        answer.AnswerJSON.ErrorAnswer.Message = errPag.Error()
        answer.AnswerJSON.Status = false
    } else {
        for _, user := range result {
            d.DB.Model(&user).Related(&user.Session)
            d.DB.Model(&user).Related(&user.UserInfo)
            d.DB.Model(&user).Related(&user.Cook)
        }
        answer.AnswerJSON.Result = result
        answer.AnswerJSON.ErrorAnswer = nil
        answer.AnswerJSON.Status = true
    }
    d.serilize(answer)
    return answer
}
//-------------------------------------------------------------------
//  category
//--------------------------------------------------------------------
func (d *Database) CategoryCreate(name string) *Answer {
    //variables
    answer := d.initCall("CategoryCreate")
    cat := new(Category)
    //check exist user
    if catExist := d.DB.Find(&Category{}, &Category{Name:name}).Error; catExist == nil {
        answer.AnswerJSON.ErrorAnswer.Message = "[categorycreate] category already exist"
        answer.AnswerJSON.Result = nil
        answer.AnswerJSON.Status = false
    } else {
        cat.Name = name
        //make request + //serizlizations to json answer
        if err := d.DB.Create(cat).Error; err != nil {
            answer.AnswerJSON.ErrorAnswer.Message = err.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Result = cat
            answer.AnswerJSON.Status = true
        }
    }
    d.serilize(answer)
    return answer
}
func (d *Database) CategoryDelete(catid int64) *Answer {
    answer := d.initCall("CategoryDelete")
    cat := new(Category)
    //check exists
    if catExists := d.DB.Find(cat, "ID = ?", catid).Error; catExists == nil {
        if catDelete := d.DB.Delete(cat).Error; catDelete != nil {
            answer.AnswerJSON.ErrorAnswer.Message = catExists.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Status = true
            answer.AnswerJSON.ErrorAnswer = nil
        }
    } else {
        answer.AnswerJSON.ErrorAnswer.Message = catExists.Error()
        answer.AnswerJSON.Status = false
    }
    d.serilize(answer)
    return answer
}
func (d *Database) CategoryRead(catid int64) *Answer {
    answer := d.initCall("CategoryRead")
    cat := new(Category)
    if catExists := d.DB.Find(cat, "ID = ?", catid).Error; catExists != nil {
        answer.AnswerJSON.ErrorAnswer.Message = catExists.Error()
        answer.AnswerJSON.Status = false
    } else {
        if rel := d.DB.Model(cat).Related(&cat.Post).Error; rel != nil {
            answer.AnswerJSON.Result = nil
            answer.AnswerJSON.ErrorAnswer.Message = rel.Error()
            answer.AnswerJSON.Status = false
        } else {
            for x, p := range cat.Post {
                d.DB.Model(&p).Related(&p.Comment)
                d.DB.Model(&p).Related(&p.PostSeo)
                cat.Post[x] = p
            }
            answer.AnswerJSON.Result = cat
            answer.AnswerJSON.ErrorAnswer = nil
            answer.AnswerJSON.Status = true
        }
    }
    d.serilize(answer)
    return answer
}
func (d *Database) CategoryReadAll() *Answer {
    answer := d.initCall("CategoryReadAll")
    cats := []Category{}

    if catsGet := d.DB.Find(&cats).Error; catsGet != nil {
        answer.AnswerJSON.ErrorAnswer.Message = catsGet.Error()
        answer.AnswerJSON.Status = false
    } else {
        //categorys
        for _, cat := range cats {
            d.DB.Model(cat).Related(&cat.Post)
            //get relete POST
            for x, p := range cat.Post {
                d.DB.Model(&p).Related(&p.Comment)
                d.DB.Model(&p).Related(&p.PostSeo)
                cat.Post[x] = p
            }
        }
        answer.AnswerJSON.Result = cats
        answer.AnswerJSON.ErrorAnswer = nil
        answer.AnswerJSON.Status = true
    }
    d.serilize(answer)
    return answer
}
func (d *Database) CategoryUpdate(catid int64, name string) *Answer {
    answer := d.initCall("CategoryUpdate")
    cat := new(Category)

    if catExists := d.DB.Find(cat, "ID = ?", catid).Error; catExists != nil {
        answer.AnswerJSON.ErrorAnswer.Message = catExists.Error()
        answer.AnswerJSON.Status = false
    } else {
        //get relevating struct info
        d.DB.Model(cat).Related(&cat.Post)

        //update columns
        if name != "" {
            cat.Name = name
        }
        //update
        if errUpdate := d.DB.Save(cat).Error; errUpdate != nil {
            answer.AnswerJSON.ErrorAnswer.Message = errUpdate.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Result = cat
            answer.AnswerJSON.ErrorAnswer = nil
            answer.AnswerJSON.Status = true
        }
    }
    d.serilize(answer)
    return answer
}
func (d *Database) CategoryPaginate(page, countPage int) *Answer {
    answer := d.initCall("CategoryPaginate")
    result := []*Category{}
    if errPag := d.DB.Limit(countPage).Offset((page * countPage) - countPage).Find(&result).Error; errPag != nil {
        answer.AnswerJSON.ErrorAnswer.Message = errPag.Error()
        answer.AnswerJSON.Status = false
    } else {
        for _, cat := range result {
            d.DB.Model(&cat).Related(&cat.Post)
            //get relete POST
            for x, p := range cat.Post {
                d.DB.Model(&p).Related(&p.Comment)
                d.DB.Model(&p).Related(&p.PostSeo)
                cat.Post[x] = p
            }
        }
        answer.AnswerJSON.Result = result
        answer.AnswerJSON.ErrorAnswer = nil
        answer.AnswerJSON.Status = true
    }
    d.serilize(answer)
    return answer
}

最佳答案

我可以看到你的代码中有很多冗余。几个月前我遇到了同样的问题并且得到了很好的答案。看看这里:How to return dynamic type struct in Golang? .

基本上你将拥有相同的三个功能(添加/编辑/删除/计数),如下所示(我不知道你使用什么数据库,我使用NoSql Rethinkdb,但原理是相同的):

func (c Main) Get(modelname string) interface{} {

   //your query here for getting stuff from model name and return interface

   rows, err := rethink.Table(modelname).OrderBy(rethink.Asc("sortNo")).Run(c.DB)
   if err != nil {
       log.Println(err)
       return nil
   }

   if (modelType == "brand") {

       var brands  []*models.Brand
       rows.All(&brands)

       return brands

   }
   //rest of your models here or use some switch
})

我通常将所有与数据库相关的函数放在一些助手中(这主要是因为测试)。

我认为这是一个很好的方向,因为这样您的代码很容易维护,并且您将只更改辅助函数,而不是去为每个模型执行添加/删除/更新的数百万个小说。

关于戈朗。重构||图案||任何解决方案,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38079036/

相关文章:

json - 字符串编码数字的自定义 JSON 解码

string - 带前导零的编号字符串到 Int

go - 在 Go 中生成 Bash Shell

colors - 使用 Color 包从 RGB 值创建新的颜色?

go - 方法执行期间内存消耗高

stream - Golang - 函数 "Execute"在哪里写入流?

json - 我可以使用嵌套值循环一些数据json吗

go - 如何在 Golang 中响应所有字段包含带有标签 omitempty 的字段?

arrays - 无法访问在另一个函数中更改的结构字段

arrays - Golang 子 slice