Golang中omitempty关键字的具体实现
知识点掌握了,还需要不断练习才能熟练运用。下面golang学习网给大家带来一个Golang开发实战,手把手教大家学习《Golang中omitempty关键字的具体实现》,在实现功能的过程中也带大家重新温习相关知识点,温故而知新,回头看看说不定又有不一样的感悟!
用法
熟悉 Golang 的朋友对于 json 和 struct 之间的转换一定不陌生,为了将代码中的结构体与 json 数据解耦,通常我们会在结构体的 field 类型后加上解释说明,例如在表示一个地址的时候, json 数据如下所示
{ "street": "200 Larkin St", "city": "San Francisco", "state": "CA", "zipcode": "94102" }
与之相对应的 Golang 结构体表示可能是这个样子的
type address struct { Street string `json:"street"` // 街道 Ste string `json:"suite"` // 单元(可以不存在) City string `json:"city"` // 城市 State string `json:"state"` // 州/省 Zipcode string `json:"zipcode"` // 邮编 }
这样无论代码中的变量如何改变,我们都能成功将 json 数据解析出来,获得正确的街道,城市等信息,到目前为止一切正常。但如果我们想要将地址结构体恢复成 json 格式时,问题就来了。比方说我们用下面这段代码读取了地址 json ,然后根据业务逻辑处理了之后恢复成正常的 json 打印出来
func main() { data := `{ "street": "200 Larkin St", "city": "San Francisco", "state": "CA", "zipcode": "94102" }` addr := new(address) json.Unmarshal([]byte(data), &addr) // 处理了一番 addr 变量... addressBytes, _ := json.MarshalIndent(addr, "", " ") fmt.Printf("%s\n", string(addressBytes)) }
这段代码的输出是
{ "street": "200 Larkin St", "suite": "", "city": "San Francisco", "state": "CA", "zipcode": "94102" }
多了一行 "suite": "", ,而这则信息在原本的 json 数据中是没有的(在美国的地址中,如果不是群租公寓或者共享办公楼, suite 这一条不存在很正常,人们直接用街道门牌号来表示地址就足够了),但我们更希望的是,在一个地址有 suite 号码的时候输出,不存在 suite 的时候就不输出,幸运的是,我们可以在 Golang 的结构体定义中添加 omitempty 关键字,来表示这条信息如果没有提供,在序列化成 json 的时候就不要包含其默认值。稍作修改,地址结构体就变成了
type address struct { Street string `json:"street"` Ste string `json:"suite,omitempty"` City string `json:"city"` State string `json:"state"` Zipcode string `json:"zipcode"` }
重新运行,即可得到正确的结果。
陷阱
带来方便的同时,使用 omitempty 也有些小陷阱,一个是该关键字无法忽略掉嵌套结构体。还是拿地址类型说事,这回我们想要往地址结构体中加一个新 field 来表示经纬度,如果没有缺乏相关的数据,暂时可以忽略。新的 struct 定义如下所示
type address struct { Street string `json:"street"` Ste string `json:"suite,omitempty"` City string `json:"city"` State string `json:"state"` Zipcode string `json:"zipcode"` Coordinate coordinate `json:"coordinate,omitempty"` } type coordinate struct { Lat float64 `json:"latitude"` Lng float64 `json:"longitude"` }
读入原来的地址数据,处理后序列化输出,我们就会发现即使加上了 omitempty 关键字,输出的 json 还是带上了一个空的坐标信息
{ "street": "200 Larkin St", "city": "San Francisco", "state": "CA", "zipcode": "94102", "coordinate": { "latitude": 0, "longitude": 0 } }
为了达到我们想要的效果,可以把坐标定义为指针类型,这样 Golang 就能知道一个指针的“空值”是多少了,否则面对一个我们自定义的结构, Golang 是猜不出我们想要的空值的。于是有了如下的结构体定义
type address struct { Street string `json:"street"` Ste string `json:"suite,omitempty"` City string `json:"city"` State string `json:"state"` Zipcode string `json:"zipcode"` Coordinate *coordinate `json:"coordinate,omitempty"` } type coordinate struct { Lat float64 `json:"latitude"` Lng float64 `json:"longitude"` }
相应的输出为
{ "street": "200 Larkin St", "city": "San Francisco", "state": "CA", "zipcode": "94102" }
另一个“陷阱”是,对于用 omitempty 定义的 field ,如果给它赋的值恰好等于默认空值的话,在转为 json 之后也不会输出这个 field 。比如说上面定义的经纬度坐标结构体,如果我们将经纬度两个 field 都加上 omitempty
type coordinate struct { Lat float64 `json:"latitude,omitempty"` Lng float64 `json:"longitude,omitempty"` }
然后我们对非洲几内亚湾的“原点坐标”非常感兴趣,于是编写了如下代码
func main() { cData := `{ "latitude": 0.0, "longitude": 0.0 }` c := new(coordinate) json.Unmarshal([]byte(cData), &c) // 具体处理逻辑... coordinateBytes, _ := json.MarshalIndent(c, "", " ") fmt.Printf("%s\n", string(coordinateBytes)) }
最终我们得到了一个
{}
这个坐标消失不见了!但我们的设想是,如果一个地点没有经纬度信息,则悬空,这没有问题,但对于“原点坐标”,我们在确切知道它的经纬度的情况下,(0.0, 0.0)仍然被忽略了。正确的写法也是将结构体内的定义改为指针
type coordinate struct { Lat *float64 `json:"latitude,omitempty"` Lng *float64 `json:"longitude,omitempty"` }
这样空值就从 float64 的 0.0 变为了指针类型的 nil ,我们就能看到正确的经纬度输出。
{ "latitude": 0, "longitude": 0 }
P.S. 本文中拿来作示例的地址是旧金山亚洲艺术博物馆的地址,藏品丰富,上到夏商周,下至明清的文物都能看到,几年前第一次去参观,很是喜欢,印象深刻。
以上就是《Golang中omitempty关键字的具体实现》的详细内容,更多关于golang的资料请关注golang学习网公众号!

- 上一篇
- Golang语言JSON解码函数Unmarshal的使用

- 下一篇
- Go中JSON解析时tag的使用
-
- 魔幻的灰狼
- 这篇技术贴真是及时雨啊,很详细,真优秀,收藏了,关注师傅了!希望师傅能多写Golang相关的文章。
- 2023-03-01 01:07:06
-
- Golang · Go教程 | 1分钟前 |
- Go语言ForkExec执行Shell问题排查
- 437浏览 收藏
-
- Golang · Go教程 | 10分钟前 |
- Golang连接池对比与实现方法解析
- 165浏览 收藏
-
- Golang · Go教程 | 19分钟前 |
- Golang实现JWT认证:jwt-go库使用教程
- 407浏览 收藏
-
- Golang · Go教程 | 24分钟前 |
- Golang数据库优化:预处理与连接池配置详解
- 214浏览 收藏
-
- Golang · Go教程 | 52分钟前 |
- 获取程序名称的正确方式
- 183浏览 收藏
-
- Golang · Go教程 | 58分钟前 |
- Golang原子替换:rename实现与事务解析
- 427浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang反射读取YAML/XML配置方法
- 422浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang反射:解锁类型系统灵活性的钥匙
- 338浏览 收藏
-
- Golang · Go教程 | 1小时前 |
- Golang反射机制在框架中的应用详解
- 359浏览 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 542次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 511次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 498次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 484次学习
-
- 千音漫语
- 千音漫语,北京熠声科技倾力打造的智能声音创作助手,提供AI配音、音视频翻译、语音识别、声音克隆等强大功能,助力有声书制作、视频创作、教育培训等领域,官网:https://qianyin123.com
- 94次使用
-
- MiniWork
- MiniWork是一款智能高效的AI工具平台,专为提升工作与学习效率而设计。整合文本处理、图像生成、营销策划及运营管理等多元AI工具,提供精准智能解决方案,让复杂工作简单高效。
- 89次使用
-
- NoCode
- NoCode (nocode.cn)是领先的无代码开发平台,通过拖放、AI对话等简单操作,助您快速创建各类应用、网站与管理系统。无需编程知识,轻松实现个人生活、商业经营、企业管理多场景需求,大幅降低开发门槛,高效低成本。
- 103次使用
-
- 达医智影
- 达医智影,阿里巴巴达摩院医疗AI创新力作。全球率先利用平扫CT实现“一扫多筛”,仅一次CT扫描即可高效识别多种癌症、急症及慢病,为疾病早期发现提供智能、精准的AI影像早筛解决方案。
- 96次使用
-
- 智慧芽Eureka
- 智慧芽Eureka,专为技术创新打造的AI Agent平台。深度理解专利、研发、生物医药、材料、科创等复杂场景,通过专家级AI Agent精准执行任务,智能化工作流解放70%生产力,让您专注核心创新。
- 93次使用
-
- Golang中omitempty的作用
- 2022-12-31 218浏览
-
- golang中json的omitempty使用操作
- 2022-12-30 466浏览