Увеличение значения структуры в Go

Я ожидаю увидеть visits увеличиваться с каждым GET просьба к /foo но остается как 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"))
}

1 ответ

Решение

Если вы зарегистрируете ошибку, например:

if err := db.Model(&i).Update("visits", i.Visits+1).Error; err != nil {
    fmt.Printf("update err != nil; %v\n", err)
}

Вы увидите, что там написано: "ГДЕ требуются условия". Итак, вы можете исправить это так:

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)
}

Вот еще несколько подробностей об обработке ошибок в GORM.


РЕДАКТИРОВАТЬ: на самом деле здесь есть более серьезная проблема с вашим примером. Проблема в том, что вы определяете UID как часть вашего Item модель, которая конфликтует с чем gorm.Modelобеспечивает. В разделе " Объявление моделей" вы можете увидеть следующее определение модели:

// 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"`
}

Похоже, это приводит к тому, что ваша таблица базы данных создается в странном состоянии. Вы могли заметить в возвращенных данных JSON, что оба ID И UID равны 0. И когда вы запускаете / останавливаете сервер несколько раз и смотрите на дополнительные записи, которые создаются (из-за вашего db.Create() вверху) вы получите несколько элементов с именем "foo", все из которых имеют ID и UID 0... вот почему GORM не может обновить элемент без предложения WHERE, поскольку первичные ключи не установлены должным образом в таблице.

Если вы удалите UID из своей модели (или, возможно, даже просто удалите из нее "primaryKey"), вы можете использовать Update()без использования условия where. Итак, ваша модель должна выглядеть так:

// Item model
type Item struct {
    gorm.Model
    Name   string `gorm:"index;not null"`
    Visits int32  `gorm:"default 0"`
}

После внесения изменений в вашу модель / тип обязательно удалите свой test.db файл, чтобы таблица была воссоздана в новом / правильном формате.


Наконец, что касается моего исходного ответа, вы также должны увидеть, что ошибки автоматически регистрируются на вашей консоли GORM без необходимости специально обрабатывать их, как я предлагал.

Другие вопросы по тегам