英文:
Why isn't the variable overwritten?
问题
如果你这样写:
func showAll(db *gorm.DB) {
users := &[]models.User{}
card := models.Card{}
db.Find(users)
for _, i := range *users {
fmt.Println(i)
db.Where("user_id = ?", i.ID).Find(&card)
fmt.Println(card)
}
}
那么fmt.Println(card)
总是打印第一个值。
但是如果你这样写:
func showAll(db *gorm.DB) {
users := &[]models.User{}
db.Find(users)
for _, i := range *users {
fmt.Println(i)
card := models.Card{}
db.Where("user_id = ?", i.ID).Find(&card)
fmt.Println(card)
}
}
它会正确打印。为什么?难道不应该覆盖&card
变量吗?
我想打印出找到的所有用户的所有卡片。
英文:
If you write it this way
func showAll(db *gorm.DB) {
users := &[]models.User{}
card := models.Card{}
db.Find(users)
for _, i := range *users {
fmt.Println(i)
db.Where("user_id = ?", i.ID).Find(&card)
fmt.Println(card)
}
}
then fmt.Println(card)
always prints the first value.
But if you write it this way
func showAll(db *gorm.DB) {
users := &[]models.User{}
db.Find(users)
for _, i := range *users {
fmt.Println(i)
card := models.Card{}
db.Where("user_id = ?", i.ID).Find(&card)
fmt.Println(card)
}
}
It prints correctly. Why? Shouldn't the &card variable be overwritten?
I wanted to print all the cards for found users.
答案1
得分: 2
你的第一个问题是你没有处理错误,如果你处理了错误,你就会知道第一个查询之后的所有查询都会导致记录未找到。你的第二个问题是你似乎不知道 gorm 有调试功能,如果你打开它,它会显示生成的 SQL,如果你查看它,你会立即发现问题所在。最后,你的实际问题是在第一次迭代之后,card
结构体实例具有非零的 ID,这与显式的 i.ID
一起在 WHERE 子句中被使用。
所以,除非 i.ID
和 card.ID
是相同的(或者 card.ID
是零),否则:
db.Where("user_id = ?", i.ID).Find(&card).Error == ErrRecordNotFound
https://gorm.io/docs/query.html#String-Conditions
如果对象的主键已经设置,那么条件查询不会涵盖主键的值,而是将其作为“and”条件使用。例如:
var user = User{ID: 10} db.Where("id = ?", 20).First(&user) // SELECT * FROM users WHERE id = 10 and id = 20 ORDER BY id ASC LIMIT 1
这个查询会导致记录未找到的错误。所以在你想要使用变量(比如 user)从数据库获取新值之前,将主键属性(比如 id)设置为 nil。
英文:
Your first problem is that you aren't handling errors, if you were then you would know that all queries after the first one result in record-not-found. Second of your problems is the fact that you don't seem to be aware that gorm has debugging which, if you turn it on, will show the generated SQL and if you were to look at that you would immediately spot what's wrong. Finally, your actual problem, is the fact that after the first iteration the card
struct instance has a non-zero ID which, alongside the explicit i.ID
is also used in the WHERE clause.
So unless i.ID
and card.ID
are identical (or card.ID
is zero) then:
db.Where("user_id = ?", i.ID).Find(&card).Error == ErrRecordNotFound
https://gorm.io/docs/query.html#String-Conditions
> If the object’s primary key has been set, then condition query wouldn’t cover the value of primary key but use it as a ‘and’ condition. For example:
>
> go
> var user = User{ID: 10}
> db.Where("id = ?", 20).First(&user)
> // SELECT * FROM users WHERE id = 10 and id = 20 ORDER BY id ASC LIMIT 1
>
>
> This query would give record not found Error. So set the primary key attribute such as id to nil before you want to use the variable such as user to get new value from database.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论