I am building a Book API in Golang using Gin and GORM. I have successfully implemented the Create, get and delete parts of the API but the Update is resulting in 500 Internal Server Error. I am trying to for a Update functionality which only updates the specific tags provided in the body(example given below). Any help or guidance is greatly appreciated.
GO Logs
[31m2022/05/09 14:08:00 [Recovery] 2022/05/09 - 14:08:00 panic recovered:
PATCH /books/2 HTTP/1.1
Host: 127.0.0.1:8080
Accept: */*
Accept-Encoding: gzip, deflate, br
Accept-Language: en-US,en;q=0.9
Connection: keep-alive
Content-Length: 66
Content-Type: text/plain;charset=UTF-8
Origin: chrome-extension://ihgpcfpkpmdcghlnaofdmjkoemnlijdi
Sec-Ch-Ua: " Not A;Brand";v="99", "Chromium";v="101", "Google Chrome";v="101"
Sec-Ch-Ua-Mobile: ?0
Sec-Ch-Ua-Platform: "Windows"
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: none
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/101.0.4951.54 Safari/537.36
reflect: call of reflect.Value.SetString on uint Value
C:/Program Files/Go/src/reflect/value.go:221 (0xc7bb04)
flag.mustBe: panic(&ValueError{methodName(), f.kind()})
C:/Program Files/Go/src/reflect/value.go:1747 (0xc7ba3e)
Value.SetString: v.mustBe(String)
C:/Users/NK086843/go/pkg/mod/gorm.io/[email protected]/schema/field.go:771 (0x10defb7)
(*Field).setupValuerAndSetter.func11: field.ReflectValueOf(ctx, value).SetString(data)
C:/Users/NK086843/go/pkg/mod/gorm.io/[email protected]/callbacks/update.go:144 (0x115b68e)
ConvertToAssignments.func2: field.Set(stmt.Context, stmt.ReflectValue, value)
C:/Users/NK086843/go/pkg/mod/gorm.io/[email protected]/callbacks/update.go:275 (0x11534f9)
ConvertToAssignments: assignValue(field, value)
C:/Users/NK086843/go/pkg/mod/gorm.io/[email protected]/callbacks/update.go:73 (0x115ac9e)
Update.func1: if set := ConvertToAssignments(db.Statement); len(set) != 0 {
C:/Users/NK086843/go/pkg/mod/gorm.io/[email protected]/callbacks.go:130 (0x10ebe14)
(*processor).Execute: f(db)
C:/Users/NK086843/go/pkg/mod/gorm.io/[email protected]/finisher_api.go:372 (0x10f4e8d)
(*DB).Updates: return tx.callbacks.Update().Execute(tx)
C:/New folder/golang/github.com/shashank-kakarla/BookAPI/controllers/books.go:101 (0x1167007)
UpdateBook: models.DB.Model(&book).Updates(input)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x10917e1)
(*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/recovery.go:99 (0x10917c7)
CustomRecoveryWithWriter.func1: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x10908c6)
(*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/logger.go:241 (0x1090885)
LoggerWithConfig.func1: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/context.go:168 (0x1086689)
(*Context).Next: c.handlers[c.index](c)
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:555 (0x108666f)
(*Engine).handleHTTPRequest: c.Next()
C:/Users/NK086843/go/pkg/mod/github.com/gin-gonic/[email protected]/gin.go:511 (0x1086112)
(*Engine).ServeHTTP: engine.handleHTTPRequest(c)
C:/Program Files/Go/src/net/http/server.go:2867 (0xe76e29)
serverHandler.ServeHTTP: handler.ServeHTTP(rw, req)
C:/Program Files/Go/src/net/http/server.go:1932 (0xe721ac)
(*conn).serve: serverHandler{c.server}.ServeHTTP(w, w.req)
C:/Program Files/Go/src/runtime/asm_amd64.s:1371 (0xc3d900)
goexit: BYTE $0x90 // NOP
←[0m
[GIN] 2022/05/09 - 14:08:00 |←[97;41m 500 ←[0m| 19.7185ms | 127.0.0.1 |←[97;42m PATCH ←[0m "/books/2"
GO Models
func UpdateBook(c *gin.Context) {
// Get model if exist
var book models.Book
if err := models.DB.Where("id = ?", c.Param("id")).First(&book).Error; err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": "Record not found!"})
return
}
// Validate input
var input UpdateBookInput
if err := c.ShouldBindJSON(&input); err != nil {
c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
models.DB.Model(&book).Updates(input)
c.JSON(http.StatusOK, gin.H{"data": book})
}
UpdateBookInput Struct
type UpdateBookInput struct {
Title string `json:"title"`
Author string `json:"author"`
}
main.go
func main() {
router := gin.Default()
models.ConnectDatabase()
router.GET("/books", controllers.FetchBooks)
router.GET("/books/:id", controllers.FindBookByID)
router.GET("/books/title/:title", controllers.FindBookByTitle)
router.GET("/books/author/:author", controllers.FindBookByAuthor)
router.POST("/books", controllers.CreateBook)
router.PATCH("/books/:id", controllers.UpdateBook)
router.DELETE("/books/:id", controllers.RemoveBook)
router.Run()
}
Request URL and Body URL
PATCH http://127.0.0.1:8080/books/2
BODY
{
"title": "Breaking Dawn",
}
Schema/Model
package models
type Book struct {
ID uint `json:"id" gorm:"primary_key"`
Title string `json:"title"`
Author string `json:"author"`
}
CodePudding user response:
I suppose the JSON data contains an ID field which is of type string, because the only uint field is ID here. Either gorm is behaving weird with Updates or its something like this.
Make sure the input is clean.
CodePudding user response:
Instead of passing the UpdateBookInput object directly, convert it to a models.Book
object.