go get github.com/go-playground/universal-translator
go get github.com/go-playground/locales
package common
import (
"github.com/gin-gonic/gin/binding"
"github.com/go-playground/locales/zh"
ut "github.com/go-playground/universal-translator"
"github.com/go-playground/validator/v10"
zhTranslations "github.com/go-playground/validator/v10/translations/zh"
"strings"
var (
uni *ut.UniversalTranslator
validate *validator.Validate
trans ut.Translator
var fieldName = map[string]string{
"Username": "用户名",
"Password": "用户密码",
"Avatar": "用户头像",
var myTags = map[string]string{
"myvalidate": "必须通过自定义方法验证",
var myvalidate validator.Func = func(fl validator.FieldLevel) bool {
val, ok := fl.Field().Interface().(string)
if ok {
if val != "gangan" {
return false
return true
func init() {
translator := zh.New()
uni = ut.New(translator, translator)
trans, _ = uni.GetTranslator("zh")
var (
validate *validator.Validate
ok bool
if validate, ok = binding.Validator.Engine().(*validator.Validate); ok {
validate.RegisterValidation("myvalidate", myvalidate)
_ = zhTranslations.RegisterDefaultTranslations(validate, trans)
func Translate(err error) string {
var result string
errors := err.(validator.ValidationErrors)
for _, err := range errors {
var (
tag = err.Tag()
field = err.Field()
msg string
if val, exist := myTags[tag]; exist {
msg = field + val + ";"
} else {
msg = err.Translate(trans) + ";"
if val, exist := fieldName[field]; exist {
msg = strings.Replace(msg, field, val, 1)
result += msg
return result
type (
RegisterRequest struct {
Username string `json:"username" binding:"required,min=3,max=25,myvalidate"`
Password string `json:"password" binding:"required,min=6,max=25"`
Avatar string `json:"avatar" binding:"required,url"`
var (
err error
res *RegisterRequest
res = new(RegisterRequest)
if err = c.ShouldBindJSON(res); err != nil {
core.ResponseError(c, common.Translate(err))
return
首先打开nginx.conf文件,在fastcgi_temp_file_write_size 128k; 下面添加 fastcgi_intercept_errors on;注意,包括;号 然后在需要定义的站点的里面添加 error_page 404 = /404.htm;例如: 代码如下: server { listen 80; server_name www.deepvps.com; index index.html index.htm index.php; error_page 404 = /404.htm; include location.conf; root /home/www/l
首先定义一个接受数据用的DTO结构体,叫做LoginDTO
type LoginDto struct {
Username string `json:"username" binding:"required" msg:"用户名不能为空"`
Password string `json:"password"
GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序GIN 27错误解决程序
个人觉的虽然gin灵活小巧,但是功能真的很不完善。每次一次输出友好信息,我们都要手动调用Translate来翻译,并且还需要通过RemoveTopStruct方法来修改返回的信息,按简单的来说,应该由框架来做,我们只需要通过配置,就能自动输出我们想要的友好提示信息才对。
为什么第二次使用ShouldBindJSON就失效了呢?
今天debug看了下,主要是 http.Request的io buffer第一次取完之后,http.body 结构体中的sawEOF=true
第二次去读取,发现已经是true了。直接返回了err = io.EOF.
导读在第二节,我们学习了Gin框架的路由定义与参数接收,今天应一位同学的要求,来讲解一下参数的绑定与校验。为什么校验参数?本不必抛出这个问题的,但顾及到初出茅庐的同学,这里解释一下。假设做一个注册接口,传过来的用户名是不是不能太骚气?比如一堆空格和符号之类的;密码是不是不能太长也不能太短?手机号是不是要符合规则?性别是不是不能填人妖?另外,登录的时候我们也需要验证账号密码是不是正确的,那么为了方便...
JSON是前后端交互的重要数据类型之一,使用Gin Web框架可以很方便地将HTTP请求报文中JSON格式的`Body`数据解析到结构体Struct或字典Map数据结构中。