Go Gin框架中如何在ShouldBindJSON中仅使用结构体的部分字段?
问题结论
三种方案中第二种独立定义API层请求结构体是符合Go语言开发规范的最优解,三个方案的优缺点和其他可选方案说明如下:
各方案优缺点分析
- 方案1:不推荐
原model层的Movie结构体本身是和数据库/核心业务实体对应的结构,required校验规则是针对全字段写入场景设计的,如果为了单个接口跳过校验,要么需要修改校验规则引入omitempty、要么自定义校验逻辑,会破坏原model结构体的语义一致性,后续其他开发者误用很容易出线上问题,也违背了分层职责分离的原则。 - 方案3:仅适合极其简单、不会复用的临时接口
匿名结构体无法复用,如果后续其他接口也需要相同的入参规则,会出现重复定义的冗余代码,而且字段校验规则如果要修改,需要逐个找所有匿名结构体修改,维护成本高,也不利于接口文档自动生成(很多Swagger生成工具不支持函数内匿名结构体解析)。 - 方案2:推荐
这是Go Web开发中标准的分层实践,API层的入参/出参结构体和model层的业务实体解耦,各自承担不同职责:- model层的结构体只对应核心业务/数据库字段,不需要耦合接口的入参校验逻辑
- API层的请求结构体只对应当前接口的入参规则,灵活适配不同接口的字段要求,不会影响其他层逻辑
- 校验规则可以集中维护,复用性高,也方便对接接口文档生成工具
优化建议
如果你的项目里同个资源的不同接口有很多相似的字段校验规则,可以用结构体嵌入的方式避免重复写标签:
// 可以放在api公共层定义通用字段校验 type MovieBaseField struct { Year uint16 `json:"year" binding:"required,lt=3000"` Title string `json:"title" binding:"required,max=255"` } // 特殊接口的入参直接嵌入即可 type MovieUpdateTitleReq struct { MovieBaseField // 有额外字段再加即可 UpdateReason string `json:"update_reason" binding:"required,max=255"` }
后续绑定完成后,只需要把API结构体的字段赋值给model层的Movie结构体做后续业务处理即可,分层清晰,维护成本低。
内容的提问来源于stack exchange,提问作者John
相关产品推荐
相关产品推荐

