1.问题描述
在编写gin框发起post请求时发现如下问题
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type Login struct {
user string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("loginJSON", func(ctx *gin.Context) {
var json Login
if err := ctx.ShouldBindJSON(&json); err != nil {
// gin.H封装了生成json数据的工具
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
fmt.Println("json.user:", json.user, "json.pssword:", json.pssword)
if json.user != "root" || json.pssword != "admin" {
ctx.JSON(http.StatusBadRequest, gin.H{"status": 304})
return
}
ctx.JSON(http.StatusOK, gin.H{"status": 200})
})
r.Run(":8001")
}
执行之后访问本地接口如下所示
curl http://127.0.0.1:8001/loginJSON -H 'content-type:application/json' -d "{\"user\":\"root\",\"password\":\"admin111\"}" -X POST
{"status":"304"}
控制台输出如下
[GIN-debug] [WARNING] Creating an Engine instance with the Logger and Recovery middleware already attached.
[GIN-debug] [WARNING] Running in "debug" mode. Switch to "release" mode in production.
- using env: export GIN_MODE=release
- using code: gin.SetMode(gin.ReleaseMode)
[GIN-debug] POST /loginJSON --> main.main.func1 (3 handlers)
[GIN-debug] [WARNING] You trusted all proxies, this is NOT safe. We recommend you to set a value.
Please check https://pkg.go.dev/github.com/gin-gonic/gin#readme-don-t-trust-all-proxies for details.
[GIN-debug] Listening and serving HTTP on :8001
json.user: json.pssword:
可以看到账号密码未打印出来
2.大小写在struct中的影响
1. 字段可访问性
首字母大写的字段(如 User, Pssword):
是可导出(Exported)的,可以被其他包访问。
序列化/反序列化库(如 JSON、XML、Gin 的 binding 等)可以正常读写这些字段。
首字母小写的字段(如 user, pssword):
是不可导出(Unexported)的,只能在当前包内访问。
外部库(如 JSON 编码器、Gin 的表单绑定器)无法直接访问这些字段,会导致序列化/反序列化失败。
Gin框架无法正常读写字段,修改之后
3.问题修正
package main
import (
"fmt"
"net/http"
"github.com/gin-gonic/gin"
)
type Login struct {
User string `form:"username" json:"user" uri:"user" xml:"user" binding:"required"`
Pssword string `form:"password" json:"password" uri:"password" xml:"password" binding:"required"`
}
func main() {
r := gin.Default()
r.POST("loginJSON", func(ctx *gin.Context) {
var json Login
if err := ctx.ShouldBindJSON(&json); err != nil {
// gin.H封装了生成json数据的工具
ctx.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
return
}
fmt.Println("json.user:", json.User, "json.pssword:", json.Pssword)
if json.User != "root" || json.Pssword != "admin" {
ctx.JSON(http.StatusBadRequest, gin.H{"status": 304})
return
}
ctx.JSON(http.StatusOK, gin.H{"status": 200})
})
r.Run(":8001")
}
C:\Users\PC>curl http://127.0.0.1:8001/loginJSON -H 'content-type:application/json' -d "{\"user\":\"root\",\"password\":\"admin\"}" -X POST
{"status":200}
可以看到访问已经正常,控制台输出也是正常的,问题解决