在工作中遇到这样一个场景,一个对象,由若干属性,比如 user 对象,有 name、birthday、height、weight、gender、race、signature,其中,每个属性的值类型不尽相同,用户可自由修改其中任意一项属性,然后提交表单,后端同学接收到表单后,需要和数据库中的内容做对比,如果发现内容更改,就修改值为表单内容。
简单的做法是将用户提交的表单内容和数据库里记录的内容做对比,如:
if record.name != form.name {
record.name = form.name
}
if record.birthday != form.birthday {
record.birthday = form.birthday
}
if record.height != form.height {
record.height= form.height
}
....
有没有更简单、直观的办法呢?
updateIfChanged := func(attribute string, fromPtr interface{}, to interface{}) int {
from := reflect.ValueOf(fromPtr).Elem()
if v := from.Interface(); v != to {
fmt.Sprintf("attribute:%s from: %v to: %v", attribute, fromPtr, to)
from.Set(reflect.ValueOf(to))
return 1
}
return 0
}
changed := updateIfChanged("name", &record.name, form.name)
.updateIfChanged("birthday", &record.birthday, form.birthday)
.updateIfChanged("height", &record.height, form.height)
.updateIfChanged("weight", &record.weight, form.weight)
.updateIfChanged("gender", &record.gender, form.gender)
.updateIfChanged("race", &record.race, form.race)
.updateIfChanged("signature", &record.signature, form.signature)
if changed > 0 {
if err = record.Update(session); err != nil {
return nil, errors.New("db error")
}
}
伴随着 Go1.18 发布,Go 语言对泛型的支持,可能还会有更多更好的办法,推荐阅读。