背景
上一章
Go语言开发基于SQLite数据库实现用户表查询详情接口(三)
这一章我们实现用户表的修改接口
代码实现
mapper层
type UserMapper interface {UpdateById(user *model.User, id uint64) error}type userMapper struct {
}func (m *userMapper) UpdateById(user *model.User, id uint64) error {return model.UpdateById(user.TableName(), user, id)
}
ModelTable实现
// UpdateById 根据 ID 更新数据
func UpdateById(tableName string, dest interface{}, id uint64) error {// 获取结构体的值和类型val := reflect.ValueOf(dest)if val.Kind() == reflect.Ptr {val = val.Elem() // 获取指向结构体的指针值}if val.Kind() != reflect.Struct {return fmt.Errorf("model must be a pointer to a struct")}var values []interface{}var setClauses []string// 遍历结构体字段,构造 SQL 语句for i := 0; i < val.NumField(); i++ {field := val.Type().Field(i)fieldValue := val.Field(i)// 获取结构体字段的数据库标签dbField := field.Tag.Get("db")if dbField == "" {// 如果没有数据库标签,就跳过该字段continue}// 仅更新非零值的字段if !isZeroValue(fieldValue) {// 构建 SET 子句setClauses = append(setClauses, fmt.Sprintf("%s = ?", dbField))values = append(values, fieldValue.Interface())}}// 如果没有可更新的字段,直接返回if len(setClauses) == 0 {return fmt.Errorf("no fields to update")}// 构建完整的 SQL 语句setClause := strings.Join(setClauses, ", ")updateSQL := fmt.Sprintf("UPDATE %s SET %s WHERE id = ?", tableName, setClause)// 将 ID 添加到参数列表的最后values = append(values, id)// 执行更新操作_, err := config.Db.Exec(updateSQL, values...)if err != nil {return err}return nil
}// isZeroValue 判断一个反射值是否为零值
func isZeroValue(v reflect.Value) bool {// 如果是指针类型,判断指针是否为 nilif v.Kind() == reflect.Ptr {return v.IsNil()}// 对于结构体,数组等类型,判断是否是其零值return v.IsZero()
}
这里我们映射的结构体中的对应db字段 , 这样的好处是我们这个方法是基础方法,其他结构体中只要有ModelTable结构体,我们就可以直接继续使用了。
service层
type UserService interface {UpdateById(user *model.User, id uint64) error}
service实现层
type UserServiceImpl struct {m mapper.UserMapper
}func (u UserServiceImpl) UpdateById(user *model.User, id uint64) error {return u.m.UpdateById(user, id)
}
controller层
type UserController struct {UserService service.UserService
}func (u *UserController) UpdateById(rc *req.Ctx) {id := uint64(req.PathParamInt(rc.GinCtx, "id"))user := new(model.User)req.BindJsonAndValid(rc.GinCtx, user)assert.IsTrue(user.Username != "" || user.PassWord != "", "账号密码需传其中一个")//user.PassWord = utils.PwdHash(user.PassWord)err := u.UserService.UpdateById(user, id)assert.IsNil(err)
}
这里也有个PathParamInt方法 路径传参,传主键ID
func PathParamInt(g *gin.Context, pm string) int {value, _ := strconv.Atoi(g.Param(pm))return value
}
接口
测试
源码地址
使用Go语言开发基于SQLite数据库实现用户表相关接口项目示例,可进行扩展,拿来即用
参考
代码风格参考的mayfly-go ,SQLite这块是自己实现的