Go中的增量结构值
Increment struct value in Go
我希望看到 visits
随着对 /foo
的每个 GET
请求的增加,但它仍然是 1
。我在这里做错了什么?
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// Item model
type Item struct {
gorm.Model
UID int64 `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&Item{})
db.Create(&Item{
Name: "foo",
})
app := fiber.New(fiber.Config{})
app.Get("/:name", func(c *fiber.Ctx) error {
var i Item
db.First(&i, "name = ?", c.Params("name"))
if i.Name == "" {
return c.Status(fiber.StatusNotFound).JSON(&fiber.Map{
"message": "Not found",
})
}
db.Model(&i).Update("visits", i.Visits+1)
return c.JSON(i)
})
log.Println("Listening...")
log.Fatal(app.Listen(":3000"))
}
如果您记录如下错误:
if err := db.Model(&i).Update("visits", i.Visits+1).Error; err != nil {
fmt.Printf("update err != nil; %v\n", err)
}
您会看到它说:“需要 WHERE 条件”。所以,你可以像这样解决这个问题:
if err := db.Model(&i).Where("name = ?", i.Name).Update("visits", i.Visits+1).Error; err != nil {
fmt.Printf("update err != nil; %v\n", err)
}
这里有一些关于 Error Handling in GORM
的更多细节
编辑:您的示例实际上存在更大的问题。问题是您将 UID
定义为 Item
模型的一部分,这与 gorm.Model
提供的内容相冲突。您可以在 Declaring Models 中看到以下模型定义:
// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
将其添加到您的 Item
类型/模型后,您将获得:
type Item struct {
// gorm.Model
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
// your fields
UID int64 `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
这似乎导致您的数据库 table 以一种奇怪的状态创建。您可能会注意到在返回的 JSON 有效负载中 ID
和 UID
都等于 0。当您多次 start/stop 服务器并查看附加记录时被创建(因为你的 db.Create()
在顶部)你最终得到多个名称为“foo”的项目,所有这些项目的 ID
和 UID
均为 0 ...这是为什么 GORM 无法在没有 WHERE 子句的情况下更新项目,因为主键没有在 table.
上正确设置
如果您从模型中删除 UID(或者甚至可能只是从中删除“primaryKey”),您就可以使用 Update()
方法而不需要 where 条件。所以,你的模型应该是这样的:
// Item model
type Item struct {
gorm.Model
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
更改模型/类型后,确保删除 test.db
文件以使 table re-created 具有新的/正确的格式。
最后,关于我的原始答案,您还应该看到 GORM 自动将错误记录到您的控制台,而无需像我建议的那样专门处理它们。
我希望看到 visits
随着对 /foo
的每个 GET
请求的增加,但它仍然是 1
。我在这里做错了什么?
package main
import (
"log"
"github.com/gofiber/fiber/v2"
"gorm.io/driver/sqlite"
"gorm.io/gorm"
)
// Item model
type Item struct {
gorm.Model
UID int64 `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
func main() {
db, err := gorm.Open(sqlite.Open("test.db"), &gorm.Config{})
if err != nil {
panic(err)
}
db.AutoMigrate(&Item{})
db.Create(&Item{
Name: "foo",
})
app := fiber.New(fiber.Config{})
app.Get("/:name", func(c *fiber.Ctx) error {
var i Item
db.First(&i, "name = ?", c.Params("name"))
if i.Name == "" {
return c.Status(fiber.StatusNotFound).JSON(&fiber.Map{
"message": "Not found",
})
}
db.Model(&i).Update("visits", i.Visits+1)
return c.JSON(i)
})
log.Println("Listening...")
log.Fatal(app.Listen(":3000"))
}
如果您记录如下错误:
if err := db.Model(&i).Update("visits", i.Visits+1).Error; err != nil {
fmt.Printf("update err != nil; %v\n", err)
}
您会看到它说:“需要 WHERE 条件”。所以,你可以像这样解决这个问题:
if err := db.Model(&i).Where("name = ?", i.Name).Update("visits", i.Visits+1).Error; err != nil {
fmt.Printf("update err != nil; %v\n", err)
}
这里有一些关于 Error Handling in GORM
的更多细节编辑:您的示例实际上存在更大的问题。问题是您将 UID
定义为 Item
模型的一部分,这与 gorm.Model
提供的内容相冲突。您可以在 Declaring Models 中看到以下模型定义:
// gorm.Model definition
type Model struct {
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
}
将其添加到您的 Item
类型/模型后,您将获得:
type Item struct {
// gorm.Model
ID uint `gorm:"primaryKey"`
CreatedAt time.Time
UpdatedAt time.Time
DeletedAt gorm.DeletedAt `gorm:"index"`
// your fields
UID int64 `gorm:"primaryKey;autoIncrement"`
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
这似乎导致您的数据库 table 以一种奇怪的状态创建。您可能会注意到在返回的 JSON 有效负载中 ID
和 UID
都等于 0。当您多次 start/stop 服务器并查看附加记录时被创建(因为你的 db.Create()
在顶部)你最终得到多个名称为“foo”的项目,所有这些项目的 ID
和 UID
均为 0 ...这是为什么 GORM 无法在没有 WHERE 子句的情况下更新项目,因为主键没有在 table.
如果您从模型中删除 UID(或者甚至可能只是从中删除“primaryKey”),您就可以使用 Update()
方法而不需要 where 条件。所以,你的模型应该是这样的:
// Item model
type Item struct {
gorm.Model
Name string `gorm:"index;not null"`
Visits int32 `gorm:"default 0"`
}
更改模型/类型后,确保删除 test.db
文件以使 table re-created 具有新的/正确的格式。
最后,关于我的原始答案,您还应该看到 GORM 自动将错误记录到您的控制台,而无需像我建议的那样专门处理它们。