Go语言中Struct增强Tag基本应用

Go 语言如何将 json 键名转为小写开头? struct 中经常用反引号包括起来的字符串,这便是 tag,一般由键值对形式存在,主要用于增强结构体的使用,可用作为判断标识进行补充处理

所属分类 Golang

相关标签 反射标签自定义

问题描述

在了解 struct tag 之前,我们有这样一个场景。

一般情况下,我们与前端会通过 JSON 格式的数据进行交互,Go 中也提供了方便的 JSON 与 struct 实体互相转换的方法。

在 Go 世界中有一个明确的规则,方法、实体、字段的名字手写字母如果不是大写,对外部包是不可见的。

而在实际业务中,这三者往往是需要被复用的,因此它们总是会被定义成首字母大写,以便于其他包获取。

字段首字母大写就带来了一个问题,转换成 JSON 格式数据输出的时候,JSON 的键名也是大写的,这很不符合大多数数据交互的习惯。

尤其对于跨语言交互时,首字母大写的键名塞给 Java 的话,对方的开发估计当场爆炸。

问题代码如下:

type User struct {
    Name string
    Age  int
    Size int
}

func main() {
    mebugs := User{"米虫", 18, 18}
    str, _ := json.Marshal(mebugs)
    fmt.Println("JSON输出=" + string(str))
}

输出结果:

JSON输出={"Name":"米虫","Age":18,"Size":18}

这时,struct tag 就可以登场了。

struct tag

Tag 是一段通过 `` (反引号) 括起来的字符串,可以有多行但是不支持任何转义。

Tag 的内容往往是成对出现的,通过空格分割不同的 tag 项,某一项的具体值可以有多个,内部通过逗号分隔。

Go 中可以通过反射机制获取所配置的 tag 名和 tag 项的具体值。

针对上文提到的字段名首字母大写的问题,如何通过 tag 来解决呢?

// 在实体中增加 tag
type User struct {
    Name string `json:"name"`    // 小写开头
    Age  int    `json:"ageYear"` // 映射任意
    Size int    `json:size`      // 错误写法
}

输出结果:

JSON输出={"name":"米虫","ageYear":18,"Size":18}

json 中 tag 如果赋值为 -,则表示该字段忽略(无论是否有值)。

注意如果 tag 中同时存在 - 和其他值,- 将会被认为是映射的字段名。

type User struct {
    Name string `json:"name"`    // 小写开头
    Age  int    `json:"ageYear"` // 映射任意
    Size int    `json:"-"`       // 忽略字段
}

输出结果:

JSON输出={"name":"米虫","ageYear":18}

json 中 tag 如果补充赋值 omitempty,如果字段有值则显示,如果没有初始化赋值或者赋空则不显示。

字符串赋空值不显示,数据类型不赋值不显示。

type User struct {
    Name string `json:"name"`           // 小写开头
    Age  int    `json:"ageYear"`        // 映射任意
    Size string `json:"size,omitempty"` // 非必传
}

多tag

除了 json 之外比较常见的就是 bson。

type User struct {
    Name string `json:"name" bson:"name"`    // BSON 是与 MongoDB 交互的数据类型
    Age  int    `json:"ageYear" bson:"name"` // 映射任意
    Size string `json:"size"`                // 非必传
}

本文主要针对比较常见的两个 tag 来举例。

Go 语言中 struct 结构体内 tag 的设计具备很大的灵活性,很多优秀的开源框架工程以及实际业务中都会运用该能力。

比如:gin 框架的 from 解析绑定前端提交的参数、自定义 valid 实现数据校验等。

米虫

做一个有理想的米虫,伪全栈程序猿,乐观主义者,坚信一切都是最好的安排!

本站由个人原创、收集或整理,如涉及侵权请联系删除

本站内容支持转发,希望贵方携带转载信息和原文链接

本站具有时效性,不提供有效、可用和准确等相关保证

本站不提供免费技术支持,暂不推荐您使用案例商业化

发表观点

提示

昵称

邮箱

QQ

网址

当前还没有观点发布,欢迎您留下足迹!

同类其他

Golang

Go语言 & 与 * 取值赋值以及函数入参的区别

在 Go 中函数可以接受值传递和指针传递,使用时就涉及到 & 内存地址(指针)与 * 指针赋值的使用,它们的区别是什么?在实际业务使用中,值传递和指针传递的分别应对什么场景需要?针对使用时机进行分析。

Go中接口的设计与实现

Go语言中的接口采用的是隐式实现,不需要去申明实现,只需要直接实现接口所定义的全部方法即可,同时区分了直接实现与指针实现两种形态,在实际使用时需要注意和关注

Go数据类型rune介绍和使用

Go 中比较常见的 int、string、bool、float 基本数据类型之外还有其他的数据类型可以应用在特殊场景,比如 rune 就是类似于 int32,因为其可表示的字符范围更大,实际工作中可以用来计算字符串的真实长度

GOPROXY依赖包代理设置

Go1.11版本开始支持包依赖管理工具,新增了GOPROXY环境变量,用于配置依赖包下载代理,通过代理配置可以实现翻墙下载一些所需的依赖包,可以说相当实用

GoLand设置gofmt和goimports代码格式化

GoLand 在保存代码时,可以自动调用 gofmt 和 goimports 实现自动格式化代码,在新版本中可以通过 File Watchers 插件来完成这些配置,配置位置位于File

Go报错xx is shadowed during return

调试 Go 程序报错 xx is shadowed during return,方法在返回的时候不是预期的返回结果,错误的产生应当是在相同作用域中出现了同名的变量导致,根据实际业务场景进行修改

选择个人头像

昵称

邮箱

QQ

网址

评论提示

  • 头像:系统为您提供了12个头像自由选择,初次打开随机为你选择一个
  • 邮箱:可选提交邮箱,该信息不会外泄,或将上线管理员回复邮件通知
  • 网址:可选提交网址,评论区该地址将以外链的形式展示在您的昵称上
  • 记忆:浏览器将记忆您已选择或填写过得信息,下次评论无需重复输入
  • 审核:提供一个和谐友善的评论环境,本站所有评论需要经过人工审核