Golang。重构||模式||任何解决方案

时间:2016-06-28 14:30:24

标签: 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
}

2 个答案:

答案 0 :(得分:2)

我可以看到你的代码中有很多冗余。几个月前,我遇到了同样的问题并得到了很好的答案。请看这里: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
})

我通常将所有正在使用数据库的函数放在一些帮助器中(这主要是因为测试)。

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

答案 1 :(得分:0)

我在代码中实现了这个想法。结果很棒。

重构代码

//------------------------------------------------------------------------
//  REFACTORING
//-----------------------------------------------------------------------
func (d *Database)Create(model string, params interface{}) *Answer {
    //variables
    answer := d.initCall("Create")
    tableType := d.Mapper[model]
    var (
        errorExists interface{}
        flag bool
    )

    //logic switch types
    switch tableType.(type) {
    case User:
        params := params.(UserUpdate)
        if errorExists = d.DB.Find(&User{}, &User{Email:params.Email}).Error; errorExists == nil {
            flag = false
        } else {
            flag = true
            //variables
            user := new(User)
            userinfo := UserInfo{Data:time.Now()}
            session := Session{Data:time.Now()}
            cook := Cook{}

            //make support  tables object
            //userinfo object
            userinfo.Password = params.Password
            userinfo.Username = params.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 = params.Email
            user.Session = session
            user.UserInfo = userinfo
            user.Cook = cook
            user.Role = int64(params.Role)

            //assign ready model for create
            tableType = user
        }

    case Category:
        params := params.(CategoryUpdate)
        if errorExists = d.DB.Find(&Category{}, &Category{Name:params.Name}).Error; errorExists == nil {
            //set logic switcher
            flag = false
        } else {
            //set logic switcher
            flag = true

            //speciffic functional
            cat := new(Category)
            cat.Name = params.Name

            //assign ready model for create
            tableType = cat
    }
    default:
        fmt.Printf("Wrong type table\n")
    }

    //call function create model
    if flag {
        if err := d.DB.Create(tableType).Error; err != nil {
            answer.AnswerJSON.ErrorAnswer.Message = err.Error()
            answer.AnswerJSON.Status = false
        } else {
            answer.AnswerJSON.Result = tableType
            answer.AnswerJSON.Status = true
        }
    } else {
        answer.AnswerJSON.ErrorAnswer.Message = "object already exist"
        answer.AnswerJSON.Result = nil
        answer.AnswerJSON.Status = false
    }
    //make answer
    d.serilize(answer)
    return answer
}