Go BeforeSave不填充数据

Go BeforeSave不填充数据,go,go-gorm,Go,Go Gorm,我有以下代码,一个非常简单的模型用户,我正在尝试更新现有用户的密码;但是,在BeforeSave中,我无法获得填充的u*User数据,因此第一次创建时,密码是散列的,但当我更新它时,密码变成纯文本。知道我做错了什么吗 package main import ( "fmt" "golang.org/x/crypto/bcrypt" "gorm.io/driver/mysql" "gorm.io

我有以下代码,一个非常简单的模型
用户
,我正在尝试更新现有用户的密码;但是,在
BeforeSave
中,我无法获得填充的
u*User
数据,因此第一次创建时,密码是散列的,但当我更新它时,密码变成纯文本。知道我做错了什么吗

package main

import (
    "fmt"

    "golang.org/x/crypto/bcrypt"
    "gorm.io/driver/mysql"
    "gorm.io/gorm"
)

type User struct {
    gorm.Model
    Username string `gorm:"type:varchar(40);unique" json:"username,omitempty"`
    Password string `gorm:"size:255" json:"password,omitempty"`
    NickName string `gorm:"type:varchar(32)" json:"nick_name,omitempty"`
}

func MakePassword(password string) (string, error) {
    bytes, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost)
    return string(bytes), err
}

// BeforeSave : hook before a user is saved
func (u *User) BeforeSave(tx *gorm.DB) (err error) {
    fmt.Println("================= user: ", u)
    if u.Password != "" {
        hash, err := MakePassword(u.Password)
        if err != nil {
            return nil
        }
        tx.Statement.SetColumn("password", hash)
    }
    return
}

func main() {
    var connectionString = fmt.Sprintf(
        "%s:%s@/%s?charset=utf8&parseTime=True&loc=Local",
        "root", "password", "myproject",
    )
    db, _ := gorm.Open(mysql.Open(connectionString), &gorm.Config{})
    db.AutoMigrate(&User{})
    db.Save(&User{
        Username: "username",
        Password: "123",
    })
    // Up to this point, everything works, password is hashed.
    // the following does not work as I expected

    userMap := make(map[string]interface{})
    userMap["id"] = 1
    userMap["password"] = "new_password"

    db.Model(&User{}).Where(&User{
        Model: gorm.Model{ID: uint(userMap["id"].(int))},
    }).Updates(userMap)
}

问题可能是您的if语句:
if u.Password!=“”
。当使用地图更新时,我几乎可以肯定将使用空模型,因此
u.Password
将为空

我用
BeforeCreate
beforefupdate
而不是
BeforeSave
这样做:

创建(tx*gorm.DB)之前的函数(u*用户)错误{ 返回u.bcryptPassword(tx) } 更新之前的func(u*用户)(tx*gorm.DB)错误{ 如果tx.Statement.已更改(“密码”){ 返回u.bcryptPassword(tx) } 归零 } func(u*用户)bcryptPassword(tx*gorm.DB)错误{ var newPass字符串 开关u:=tx.Statement.Dest.(类型){ 案例映射[字符串]接口{}: newPass=u[“密码”]。(字符串) 案例*用户: newPass=u.密码 案例[]*用户: newPass=u[tx.Statement.CurDestIndex]。密码 } b、 错误:=bcrypt.GenerateFromPassword([]字节(newPass),10) 如果错误!=零{ 返回错误 } tx.Statement.SetColumn(“密码”,b) 归零 } 您应该依赖给定的gorm事务,而不是
u
变量

注意:此实现也适用于批处理操作和使用映射(而不是结构)进行插入/更新