Go web中修改操作需要注意的一点
不仅是Gin框架,曾经在http库中也遇到过类似的问题,所以进行详细的分析!
定位到前端代码:bubble_frontend/TodoList.vue at master · Q1mi/bubble_frontend (github.com)
handleEdit(index, row) {
let messageSuffix = row.status ? " 置为未完成" : " 置为已完成";
this.axios
.put("/v1/todo/" + row.id, {
status: !row.status
})
.then(() => {
this.tableData[index].status = !row.status;
this.$message({
showClose: true,
duration: 1500,
message: `<${row.title}> ${messageSuffix}`,
type: "success"
});
});
},
status为bool类型。
可以清楚的看到,前端向/v1/todo/:id
发送了PUT请求,并且发送了!status
。
同时可以在服务器端,截取到完整的请求信息来验证,这里参考了:Gin 框架优雅的获取所有的请求参数 | 热浪编程 (pudongping.com)
// 修改某一个待办事项
v1Group.PUT("/todo/:id", func(c *gin.Context) {
id, ok := c.Params.Get("id")
if !ok {
c.JSON(http.StatusOK, gin.H{"error": "无效的id"})
return
}
var todo Todo
if err = DB.Where("id=?", id).First(&todo).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
return
}
// 此时的todo是从数据库取出的:{ID:1 Title:吃饭 Status:false}
c.BindJSON(&todo) // 这一步,c中有前端传来的{"status":true};
if err = DB.Save(&todo).Error; err != nil {
c.JSON(http.StatusOK, gin.H{"error": err.Error()})
} else {
c.JSON(http.StatusOK, todo)
}
})
疑问:{ID:1 Title:吃饭 Status:false}
经过 c.BindJSON(&todo)
之后,就修改为 {ID:1 Title:吃饭 Status:true}
- c中只有前端传来的
{"status":true}
,Todo结构体的部分成员变量。
经过对c.BindJSON(&todo)
的源码分析,最终发现核心起作用的是关于json.Decoder
,并对其做出如下模拟:
type Person struct {
Name string `json:"name"`
Age int `json:"age"`
}
func main() {
str := `{"age":18}` // 模拟前端传来的某条参数;
person := Person{Name: "老六", Age: 27} // 模拟数据库中已有的记录;
err := json.NewDecoder(strings.NewReader(str)).Decode(&person)
if err == nil {
fmt.Printf("解码结果: %+v", person)
} // 解码结果: {Name:老六 Age:18}
}
总结:对于Go语言常见的库,应该扎实掌握!