Golang中匿名结构体嵌入时如何仅引用原结构体的指定部分字段
你原来的通过同名字段遮蔽+json:"-"的方式仅能实现JSON序列化层面的字段屏蔽,代码层面仍然可以通过嵌入的User匿名结构体访问到被屏蔽的字段,且后续User新增敏感字段需要同步维护遮蔽规则,维护成本较高。更合理的实现方式有以下几种:
方案1:显式声明所需字段(最直接,无冗余)
放弃匿名嵌入整个User结构体,直接在UserInfo中声明你需要的字段,从定义层面完全剔除不需要的字段:
type UserInfo struct { UserId int Org int Name string Avatar string Addresses []Address }
- 优点:无任何冗余字段,代码访问和序列化层面都不会泄露敏感字段,逻辑最简单清晰
- 缺点:如果需要复用的字段较多,会有重复定义的冗余
方案2:抽离公共基础结构体(最推荐,适合工程化项目)
从模型定义层面对字段做职责拆分,将需要复用的非敏感字段抽为独立的基础结构体,原User和UserInfo分别基于基础结构体扩展自身需要的字段:
// 抽离的公共非敏感用户字段 type UserBase struct { UserId int Org int Name string Avatar string } // 原完整User实体,扩展敏感字段 type User struct { UserBase Password string Sex int Age int } // DAO层使用的UserInfo,扩展地址列表 type UserInfo struct { UserBase Addresses []Address }
- 优点:符合单一职责原则,字段定义唯一,后续修改公共字段只需要改一处,无维护冗余,从根源上避免敏感字段泄露
- 缺点:需要调整原有的实体定义结构
方案3:自定义序列化逻辑(适合仅需要序列化屏蔽的场景)
如果不需要调整原有结构体定义,且仅需要在序列化对外输出时屏蔽字段,可以为UserInfo实现自定义的序列化接口,主动控制需要输出的字段:
import "encoding/json" func (u UserInfo) MarshalJSON() ([]byte, error) { // 仅序列化需要的字段 return json.Marshal(&struct { UserId int `json:"user_id"` Org int `json:"org"` Name string `json:"name"` Avatar string `json:"avatar"` Addresses []Address `json:"addresses"` }{ UserId: u.User.UserId, Org: u.User.Org, Name: u.User.Name, Avatar: u.User.Avatar, Addresses: u.Address, }) }
- 优点:不需要调整原有结构体定义,灵活控制序列化输出内容
- 缺点:仅能屏蔽序列化结果,代码层面仍然可以访问到
User的敏感字段,内部使用时仍有泄露风险
内容的提问来源于stack exchange,提问作者Yun Fu
相关产品推荐
相关产品推荐

