反映:在 GORM 更新操作的 uint 值上调用 reflect.Value.SetString

reflect: call of reflect.Value.SetString on uint Value on GORM Updates operation

我正在尝试使用 Golang、Gin 和 GORM 构建一个简单的 CRUD 博客。但是,当我想更新博客内容时,触发了以下错误:

reflect: call of reflect.Value.SetString on uint Value
/usr/local/go/src/reflect/value.go:223 (0x10bfb25)
        flag.mustBe: panic(&ValueError{methodName(), f.kind()})
/usr/local/go/src/reflect/value.go:2292 (0x10bfaa3)
        Value.SetString: v.mustBe(String)
/Users/sam/go/pkg/mod/gorm.io/gorm@v1.23.5/schema/field.go:771 (0x144fcfc)
        (*Field).setupValuerAndSetter.func11: field.ReflectValueOf(ctx, value).SetString(data)
/Users/sam/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:144 (0x14b7d9a)
        ConvertToAssignments.func2: field.Set(stmt.Context, stmt.ReflectValue, value)
/Users/sam/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:275 (0x14b62fa)
        ConvertToAssignments: assignValue(field, value)
/Users/sam/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks/update.go:73 (0x14b4fe4)
        Update.func1: if set := ConvertToAssignments(db.Statement); len(set) != 0 {
/Users/sam/go/pkg/mod/gorm.io/gorm@v1.23.5/callbacks.go:130 (0x146d632)
        (*processor).Execute: f(db)
/Users/sam/go/pkg/mod/gorm.io/gorm@v1.23.5/finisher_api.go:372 (0x1476811)
        (*DB).Updates: return tx.callbacks.Update().Execute(tx)
/Volumes/Data/Develop/Go/go-blog/controllers/blog.go:65 (0x1693364)
        UpdateBlog: models.DB.Model(&blog).Updates(input)
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x168a121)
        (*Context).Next: c.handlers[c.index](c)
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/recovery.go:99 (0x168a10c)
        CustomRecoveryWithWriter.func1: c.Next()
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1689246)
        (*Context).Next: c.handlers[c.index](c)
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/logger.go:241 (0x1689229)
        LoggerWithConfig.func1: c.Next()
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/context.go:168 (0x1688310)
        (*Context).Next: c.handlers[c.index](c)
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:555 (0x1687f78)
        (*Engine).handleHTTPRequest: c.Next()
/Users/sam/go/pkg/mod/github.com/gin-gonic/gin@v1.7.7/gin.go:511 (0x1687ab1)
        (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
/usr/local/go/src/net/http/server.go:2916 (0x129bf5a)
        serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
/usr/local/go/src/net/http/server.go:1966 (0x1296f56)
        (*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
/usr/local/go/src/runtime/asm_amd64.s:1571 (0x10648a0)
        goexit: BYTE    [=11=]x90   // NOP

然而,当我跟随tutorial时,一切都很好。这是我的代码:

package controllers

import (
    "net/http"
    "samzhangjy/go-blog/models"

    "github.com/gin-gonic/gin"
)

type CreateBlogInput struct {
    Title   string `json:"title" binding:"required"`
    Content string `json:"content" binding:"required"`
}

func CreateBlog(c *gin.Context) {
    var input CreateBlogInput
    if err := c.ShouldBindJSON(&input); err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    blog := models.Blog{Title: input.Title, Content: input.Content}
    models.DB.Create(&blog)

    c.JSON(http.StatusOK, gin.H{"data": blog})
}

func FindBlogs(c *gin.Context) {
    var blogs []models.Blog
    models.DB.Find(&blogs)

    c.JSON(http.StatusOK, gin.H{"data": blogs})
}

func FindBlog(c *gin.Context) {
    var blog models.Blog

    if err := models.DB.First(&blog, "id = ?", c.Param("id")).Error; err != nil {
        c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": err.Error()})
        return
    }

    c.JSON(http.StatusOK, gin.H{"data": blog})
}

type UpdateBlogInput struct {
    Title   string `json:"title"`
    Content string `json:"content"`
}

func UpdateBlog(c *gin.Context) {
    var blog models.Blog
    if err := models.DB.Where("id = ?", c.Param("id")).First(&blog).Error; err != nil {
        c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "record not found"})
        return
    }

    var input UpdateBlogInput

    if err := c.ShouldBindJSON(&input); err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    models.DB.Model(&blog).Updates(input)
    c.JSON(http.StatusOK, gin.H{"data": blog})
}

我已阅读 ,但答案没有太大帮助。当我将空数据传递给控制器​​时,一切正常。但是如果我在请求正文中写一些要更新的东西,例如:

{ "title": "lorem ipsum" }

会崩溃并抛出上述异常

提前致谢!

更新:

我的以下模型:

package models

import "time"

type Blog struct {
    ID        uint      `json:"id" gorm:"primary_key"`
    Title     string    `json:"title"`
    Content   string    `json:"content"`
    CreatedAt time.Time `json:"created_at"`
}

可能是因为您使用的结构不同于 models.Blog 进行更新。您可以尝试以下操作吗:

func UpdateBlog(c *gin.Context) {
    var blog models.Blog
    if err := models.DB.Where("id = ?", c.Param("id")).First(&blog).Error; err != nil {
        c.AbortWithStatusJSON(http.StatusNotFound, gin.H{"error": "record not found"})
        return
    }

    var input UpdateBlogInput

    if err := c.ShouldBindJSON(&input); err != nil {
        c.AbortWithStatusJSON(http.StatusBadRequest, gin.H{"error": err.Error()})
        return
    }

    updateBlog := models.Blog{Title: input.Title, Content: input.Content}

    models.DB.Model(&blog).Updates(&updateBlog)
    c.JSON(http.StatusOK, gin.H{"data": updateBlog})
}