Home > Software engineering >  Update struct object with PATCH request
Update struct object with PATCH request

Time:08-07

So i have built a simple REST API with Gin, that can make POST, and GET requests to add user objects and retrieve them. The users are of type struct, and and are stored in a slice. This just runs in memory, and is therefore not connected to a database.

I wanted to create a new function, that can update an existing user with a PATCH request, but what i made doesn't seem to work correctly:

func updateUser(c *gin.Context) {

    id := c.Param("id")

    var updatedUser user

    if err := c.BindJSON(&updatedUser); err != nil {
        return
    }

    updatedId := updatedUser.ID
    updatedFirstName := updatedUser.FirstName
    updatedLastName := updatedUser.LastName
    updatedEmail := updatedUser.Email

    for _, user := range users {
        if updatedUser.ID == id {
            user.ID = updatedId
            user.FirstName = updatedFirstName
            user.LastName = updatedLastName
            user.Email = updatedEmail
            users = append(users, updatedUser)
            c.JSON(http.StatusCreated, gin.H{"success": "user updated"})
            return
        }
    }
    c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
}

This just creates a new user and appends it to the end of my slice, instead of updating the user with id specified in the URL with the request. How can i make this function work, to update the values of my user object, while still keeping the same order in the slice?

CodePudding user response:

Your code creates a copy of the user, changes it, and appends it to the end of the slice. If you want to amend a user then you can do something like this:

for i := range users {
    if users[i].ID == id {
        users[i].ID = updatedId // Are you sure this is what you want!
        users[i].FirstName = updatedFirstName
        users[i].LastName = updatedLastName
        users[i].Email = updatedEmail
        c.JSON(http.StatusOK, gin.H{"success": "user updated"})
        return
    }
    c.JSON(http.StatusNotFound, gin.H{"error": "user not found"})
}

A few notes on this:

  • Assumes that the slice will only ever contain one user with that ID.
  • Allows the logged on user (I assume that is what c.Param("id") is) to update their own ID. This is not something you would generally want to do (I could just change my user ID to the ID of an admin user and, potentially, gain admin access).
  • A patch request "applies partial modifications to a resource" so generally you would only update the attributes that are provided (rather than replacing everything - that would be a PUT).
  • Currently this code is not threadsafe; multiple users might make simultaneous patch requests (potential data races)
  •  Tags:  
  • go
  • Related