英文:
Update struct object with PATCH request
问题
所以我用Gin构建了一个简单的REST API,可以进行POST和GET请求来添加用户对象和检索它们。用户是结构体类型,并且存储在一个切片中。这只是在内存中运行,因此没有连接到数据库。
我想创建一个新的函数,可以使用PATCH请求更新现有用户,但是我做的似乎不正确:
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"})
}
这只是创建一个新用户并将其附加到切片的末尾,而不是使用请求中指定的URL中的ID更新用户。如何使这个函数工作,以更新用户对象的值,同时保持切片中的相同顺序?
英文:
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?
答案1
得分: 1
你的代码创建了用户的副本,对其进行更改,并将其附加到切片的末尾。如果你想修改一个用户,可以像这样做:
for i := range users {
if users[i].ID == id {
users[i].ID = updatedId // 你确定这是你想要的吗!
users[i].FirstName = updatedFirstName
users[i].LastName = updatedLastName
users[i].Email = updatedEmail
c.JSON(http.StatusOK, gin.H{"success": "用户已更新"})
return
}
c.JSON(http.StatusNotFound, gin.H{"error": "未找到用户"})
}
对此有几点说明:
- 假设切片中只会有一个具有该ID的用户。
- 允许已登录的用户(我猜这就是
c.Param("id")
的含义)更新自己的ID。这通常不是你想要做的事情(我可以将我的用户ID更改为管理员用户的ID,并有可能获得管理员权限)。 - PATCH请求“对资源应用部分修改”,因此通常只会更新提供的属性(而不是替换所有内容,那将是PUT请求)。
- 目前这段代码不是线程安全的;多个用户可能同时进行补丁请求(可能导致数据竞争)。
英文:
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)
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论