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 有效负载中 IDUID 都等于 0。当您多次 start/stop 服务器并查看附加记录时被创建(因为你的 db.Create() 在顶部)你最终得到多个名称为“foo”的项目,所有这些项目的 IDUID 均为 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 自动将错误记录到您的控制台,而无需像我建议的那样专门处理它们。