0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【GORM】Modelメソッドにはポインタ型の構造体を渡そう

Posted at

一般的にCRUDする分には、Modelメソッドに値型の構造体を渡しても動作はします。

if err := db.Debug().
    Model(User{}).
    Where("id = ?", 1).
    Updates(User{Age: 30}).Error; err != nil {
	fmt.Println("error:", err)
}

発生するエラー

しかし、Hooksを設定している状態で、Modelメソッドに値型の構造体を渡すと、以下のようなエラーが出力されます。

invalid value, should be pointer to struct or slice

Hooksとは

特定のテーブルに対して作成、取得、更新、削除の操作を行う前後に自動的に呼び出される関数のことです。
参考: https://gorm.io/ja_JP/docs/hooks.html

エラーが発生するコード例

func dbInit() *gorm.DB {
	dsn := "root:@tcp(127.0.0.1:3306)/verify_db?charset=utf8mb4&parseTime=True&loc=Local"
	db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
	if err != nil {
		fmt.Println("gorm open error:", err)
	}
	return db
}

type User struct {
	ID           uint
	Name         string
	Email        *string
	Age          uint8
	Birthday     *time.Time `gorm:"type:date"`
	MemberNumber *string
	ActivatedAt  *time.Time
	CreatedAt    time.Time
	UpdatedAt    time.Time
}

func (u *User) BeforeSave(tx *gorm.DB) (err error) {
	fmt.Println("BeforeSave run")
	return
}

func main() {
    db := dbInit()
    
	if err := db.Debug().
		Model(User{}). // 値型の構造体だとエラー
		Where("id = ?", 1).
		Update("age", 20).Error; err != nil {
		fmt.Println("query error:", err)
	}
}

このコードを実行すると、以下のようにエラーが発生します。

% go run main.go
query error: invalid value, should be pointer to struct or slice

User構造体に定義したBeforeSaveメソッドが呼び出される前に、エラーで処理が中断されてしまいます。

解決方法

if err := db.Debug().
	Model(&User{}). // ポインタ型の構造体に変更
	Where("id = ?", 1).
	Update("age", 20).Error; err != nil {
	fmt.Println("query error:", err)
}

基本的には、Modelメソッドにはポインタ型の構造体を渡すようにしましょう。

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?