我正在使用 gorm,调用 Create 方式时,传递值对象和引用对象有什么区别

179 天前
 RedBeanIce
```go
package main

import (
"fmt"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
"time"
)

type User struct {
gorm.Model
Name string
Age int
}

func main() {
// 使用 SQLite 内存数据库进行演示
db, err := gorm.Open(sqlite.Open("file::memory:?cache=shared"), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})

// 使用引用对象
userRef := &User{Name: "John", Age: 25}
resultRef := db.Create(userRef)
fmt.Printf("Reference Object: %+v\n", userRef)
fmt.Printf("RowsAffected: %d\n", resultRef.RowsAffected)

// 使用值对象
userVal := User{Name: "Jane", Age: 30}
resultVal := db.Create(&userVal)
fmt.Printf("Value Object: %+v\n", userVal)
fmt.Printf("RowsAffected: %d\n", resultVal.RowsAffected)
}
```

id 字段均已更新,
581 次点击
所在节点    Go 编程语言
8 条回复
Smilencer
179 天前
在第一个 Create 中使用了引用对象,即使用了已经存在的对象的引用进行数据库操作。这种情况下,GORM 在操作后会更新这个对象的属性,例如在数据库生成的自增 ID 会反映在原始的对象中。

而在第二个 Create 中使用了值对象,即直接使用对象本身进行数据库操作。在这种情况下,GORM 操作数据库后不会更新原始的对象属性。因此,在第二个示例中,userVal 对象的属性不会被更新为数据库生成的值。

-- by chatgpt
nagisaushio
179 天前
你这俩都是用引用啊,所以没区别
RedBeanIce
179 天前
```

import (
"fmt"

"gorm.io/driver/mysql"
"gorm.io/gorm"
)

type User struct {
gorm.Model
Name string
Age int
}

func main() {
dsn := "root:123456@tcp(127.0.0.1:3306)/go_mysql?charset=utf8mb4&parseTime=True&loc=Local"
db, err := gorm.Open(mysql.Open(dsn), &gorm.Config{})
if err != nil {
panic("failed to connect database")
}
db.AutoMigrate(&User{})

// 使用引用对象
userRef := &User{Name: "John", Age: 25}
resultRef := db.Create(userRef)
fmt.Printf("Reference Object: %+v\n", userRef)
fmt.Printf("RowsAffected: %d\n", resultRef.RowsAffected)

// 使用值对象
userVal := User{Name: "Jane", Age: 30}
resultVal := db.Create(&userVal)
fmt.Printf("Value Object: %+v\n", userVal)
fmt.Printf("RowsAffected: %d\n", resultVal.RowsAffected)
}



Reference Object: &{Model:{ID:1 CreatedAt:2023-11-24 22:50:17.388 +0800 CST UpdatedAt:2023-11-24 22:50:17.388 +0800 CST DeletedAt:{Time:0001-01-01 00:00:00 +0000 UTC Valid:false}} Name:John Age:25}
RowsAffected: 1
Value Object: {Model:{ID:2 CreatedAt:2023-11-24 22:50:17.401 +0800 CST UpdatedAt:2023-11-24 22:50:17.401 +0800 CST DeletedAt:{Time:0001-01-01 00:00:00 +0000 UTC Valid:false}} Name:Jane Age:30}
RowsAffected: 1



```
RedBeanIce
179 天前
@nagisaushio 额,,我感觉好像理解的不对嘛,,我试了试



```
type User struct {
// gorm.Model
Name string
Age int
}

func main() {
user := User{Name: "John", Age: 25}

// 调用接收值的方法
changeAge(user)
fmt.Println("After changeAge:", user)

// 调用接收引用的方法
changeAge2(&user)
fmt.Println("After changeAge2:", user)
}

func changeAge(user User) {
// 对 user 进行操作,不会影响原始对象
user.Age = user.Age + 1
fmt.Println("Inside changeAge:", user)
}

func changeAge2(user *User) {
// 对 user 进行操作,会影响原始对象
user.Age = user.Age + 1
fmt.Println("Inside changeAge2:", *user)
}



```

Inside changeAge: {John 26}
After changeAge: {John 25}
Inside changeAge2: {John 26}
After changeAge2: {John 26}

值,还是,引用,都是自己控制的
RedBeanIce
179 天前
@Smilencer 假的,我问之前,已经问过 gpt 了。
nagisaushio
179 天前
你仔细看看,主贴写的两次传给 db.Create 的都是 *User 类型
RedBeanIce
179 天前
@nagisaushio 第二次传递过去的,,加了 &,,

yes 大佬。你是对的。
RedBeanIce
179 天前
@Smilencer gpt 是对的。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/994976

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX