【Go】结构体中Tag标识

https://blog.csdn.net/weixin_45193103/article/details/123876319
https://blog.csdn.net/qq_49723651/article/details/122005291
https://juejin.cn/post/7005465902804123679
学一点,整一点,基本都是综合别人的,弄成我能理解的内容

Tag定义

Tag用于标识结构体字段的额外属性,有点类似于注释。标准库reflect包中提供了操作Tag的方法

Tag是结构体在编译阶段关联到成员的元信息字符串,在运行的时候通过反射的机制读取出来。

结构体的字段的定义。在reflect包中,使用结构体structField表示结构体的一个字段

type StructField struct {Name string//字段名Type Type//字段类型Tag StructTag     //Tag 的类型为structTag,实际上它是一个string类型的别名//Tag
}

key会指定反射的解析方式,如下: json(JSON标签) 、orm(Beego标签)、gorm(GORM标签)、bson(MongoDB标签)、form(表单标签)、binding(表单验证标签)、yaml

Tag的意义

Go语言的反射特性可以动态地给结构体成员赋值,正是因为有Tag,在赋值前可以使用Tag来决定赋值的动作。
比如,官方的encoding/json包可以将一个JSON 数据“Unmarshal”进一个结构体,此过程中就使用了 Tag。该包定义了一些Tag 规则,只要参考该规则设置tag 就可以将不同的JSON数据转换成结构体。

在Golang中,命名都是推荐用驼峰方式,并且在首字母大小写有特殊的语法含义:包外无法引用。但是由于经常需要和其它的系统进行数据交互,例如转成json格式,存储到mongodb啊等等。这个时候如果用属性名来作为键值可能不一定会符合项目要求。
而通过Tag,我们可以在转换成其它格式的时候,使用其中定义的字段作为键值。

type User struct {UserId int `json:"user_id"`UserName string `json:"user_name"`
}
func main()  {u := &User{UserId: 1, UserName: "张三"}j, _ := json.Marshal(u)fmt.Println(string(j))
}//{"user_id":1,"user_name":"张三"}

Tag约定

结构体标签由一个或多个键值对组成。键与值使用冒号分隔,值用双引号括起来。键值对之间使用一个空格分隔,具体的格式如下:

`key1:"value1" key2:"value2" key3:"value3"...`  // 键值对用空格分隔

Tag 本身是一个字符串,单从语义上讲,任意的字符串都是合法的。但它有一个约定的格式,那就是字符串由key:"value"组成。
key 必须是非空字符串,字符串不能包含控制字符、空格、引号、冒号;
value 以双引号标记的字符串。
注意: key和 value之间使用冒号分隔,冒号前后不能有空格,多个key : "value"之间由空格分开。

Kind string `json:"kind, omitempty" protobuf:"bytes,1, opt, name=kind"`

key一般表示用途,比如.json表示用于控制结构体类型与JSON格式数据之间的转换,protobuf表示用于控制序列化和反序列化。value一般表示控制指令,具体控制指令由不同的库指定。

获取Tag值

package mainimport ("fmt""reflect"
)type Food struct {Apple string `fruit:"apple"`Tomato string `vegetable:"tomato"`
}func main() {t := reflect.TypeOf(Food{})f, _ := t.FieldByName("Apple")fmt.Println(f.Tag)// Tag.Lookupv, ok := f.Tag.Lookup("fruit")fmt.Printf("%s, %t\n", v, ok)// Tag.Getv = f.Tag.Get("fruit")fmt.Println(v)
}

运行结果

fruit:"apple"
apple, true
apple

json Tag

type Student struct {ID   int     `json:"-"`            // 该字段不进行序列化Name string  `json:name,omitempy`  // 如果为类型零值或空值,序列化时忽略该字段Age  int     `json:age,string`     // 重新指定字段类型,支持string、number、boolen
}

https://studygolang.com/static/pkgdoc/pkg/encoding_json.htm

json编码

type User struct {ID   int `json:"id"`  // 编码后的字段名为 idName string           // 编码后的字段名为 自定义成员名 Nameage  int              // 未导出字段不能编码
}

在 Go 语言中,如果一个结构体的字段名首字母是大写,那么它就是一个 “导出字段”(Exported Field),意味着它可以被外部的包访问和操作。反之,如果一个字段名首字母是小写,那么它就是一个 “未导出字段”(Unexported Field),只能在当前的包内部被访问和操作。
在进行 JSON 编码(encoding)或解码(decoding)时,只有结构体的导出字段才会被处理。

gorm

GORM Tag名大小写不敏感,建议使用camelCase风格,多个标签定义用分号(;)分隔
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

// 新闻模型
type News struct {ModelTitle   string   `gorm:"column:title;type:string;not null,default:''"`Content Content  `gorm:"foreignKey:NewsId" json:"content"` //指定外键
}
// AUTO_INCREMENT 不生效
Id  uint64 `gorm:"column:id;primaryKey;type:bigint(20);autoIncrement;comment:'主键'"`
// AUTO_INCREMENT 不生效
Id  uint64 `gorm:"column:id;type:bigint(20);autoIncrement;comment:'主键'"`
// AUTO_INCREMENT 生效 gorm会自动根据字段类型设置数据库字段类型并设置为主键
Id  uint64 `gorm:"column:id;autoIncrement;comment:'主键'"` //写成AUTO_INCREMENT也可以

yaml inline

在 Go 语言结构体标签(struct tags)中,yaml:",inline" 是一种特殊的标识符,表示“内联”,也就是嵌入。
这个标识符的作用主要有两层含义:

  • 对于 Go 语言的结构体字段(Struct Fields)本身,如果这个字段的类型是另一个结构体,那么在编组和解组这个结构体的时候,它的字段会被当作是外层结构体的字段来处理。
  • 对于解析 YAML 文件时,如果一个字段被标记为 inline,那么在这个 YAML 文件被解析成 Go 语言结构体的时候,这个字段将会把它的子节点看作是自己的直接字段。
type Person struct {Name string `yaml:"name"`Age  int    `yaml:"age"`
}type Employee struct {Person `yaml:",inline"`Job    string `yaml:"job"`
}

当你在解析如下的 YAML 时:

yaml
name: Mike
age: 30
job: engineer

那么,这个 YAML 将会被解析成如下的 Go 语言结构体:

Employee{Person: Person{Name: "Mike",Age:  30,},Job: "engineer",
}

可以看到,虽然 YAML 文件中并没有 Person 这一层,但是由于 Person 被标记为 inline,Name 和 Age 字段就像是 Employee 的直接字段一样被处理了。

xml


func ExampleMarshalIndent() {type Address struct {City, State string}type Person struct {XMLName   xml.Name `xml:"person"`Id        int      `xml:"id,attr"`FirstName string   `xml:"name>first"`LastName  string   `xml:"name>last"`Age       int      `xml:"age"`Height    float32  `xml:"height,omitempty"`Married   boolAddressComment string `xml:",comment"`}v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}v.Comment = " Need more details. "v.Address = Address{"Hanga Roa", "Easter Island"}output, err := xml.MarshalIndent(v, "  ", "    ")if err != nil {fmt.Printf("error: %v\n", err)}os.Stdout.Write(output)// Output://   <person id="13">//       <name>//           <first>John</first>//           <last>Doe</last>//       </name>//       <age>42</age>//       <Married>false</Married>//       <City>Hanga Roa</City>//       <State>Easter Island</State>//       <!-- Need more details. -->//   </person>
}func ExampleEncoder() {type Address struct {City, State string}type Person struct {XMLName   xml.Name `xml:"person"`Id        int      `xml:"id,attr"`FirstName string   `xml:"name>first"`LastName  string   `xml:"name>last"`Age       int      `xml:"age"`Height    float32  `xml:"height,omitempty"`Married   boolAddressComment string `xml:",comment"`}v := &Person{Id: 13, FirstName: "John", LastName: "Doe", Age: 42}v.Comment = " Need more details. "v.Address = Address{"Hanga Roa", "Easter Island"}enc := xml.NewEncoder(os.Stdout)enc.Indent("  ", "    ")if err := enc.Encode(v); err != nil {fmt.Printf("error: %v\n", err)}// Output://   <person id="13">//       <name>//           <first>John</first>//           <last>Doe</last>//       </name>//       <age>42</age>//       <Married>false</Married>//       <City>Hanga Roa</City>//       <State>Easter Island</State>//       <!-- Need more details. -->//   </person>
}// This example demonstrates unmarshaling an XML excerpt into a value with
// some preset fields. Note that the Phone field isn't modified and that
// the XML <Company> element is ignored. Also, the Groups field is assigned
// considering the element path provided in its tag.
func ExampleUnmarshal() {type Email struct {Where string `xml:"where,attr"`Addr  string}type Address struct {City, State string}type Result struct {XMLName xml.Name `xml:"Person"`Name    string   `xml:"FullName"`Phone   stringEmail   []EmailGroups  []string `xml:"Group>Value"`Address}v := Result{Name: "none", Phone: "none"}data := `<Person><FullName>Grace R. Emlin</FullName><Company>Example Inc.</Company><Email where="home"><Addr>gre@example.com</Addr></Email><Email where='work'><Addr>gre@work.com</Addr></Email><Group><Value>Friends</Value><Value>Squash</Value></Group><City>Hanga Roa</City><State>Easter Island</State></Person>`err := xml.Unmarshal([]byte(data), &v)if err != nil {fmt.Printf("error: %v", err)return}fmt.Printf("XMLName: %#v\n", v.XMLName)fmt.Printf("Name: %q\n", v.Name)fmt.Printf("Phone: %q\n", v.Phone)fmt.Printf("Email: %v\n", v.Email)fmt.Printf("Groups: %v\n", v.Groups)fmt.Printf("Address: %v\n", v.Address)// Output:// XMLName: xml.Name{Space:"", Local:"Person"}// Name: "Grace R. Emlin"// Phone: "none"// Email: [{home gre@example.com} {work gre@work.com}]// Groups: [Friends Squash]// Address: {Hanga Roa Easter Island}
}

Go vet

vet 是 golang 中自带的静态分析工具,可以让我们检查出 package 或者源码文件中一些隐含的错误

Go 编译器没有强制执行传统的 struct 标签格式,但是 vet 就是这样做的,所以值得使用它,例如作为 CI 管道的一部分。

type T struct {f string "one two three"
}
func main() {}> Go vet tags.go
tags.go:4: struct field tag `one two three` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair
//在 Go 语言中,当你使用结构体标签(struct tag)去描述一个结构体中的字段时,其格式必须严格遵守 "键:值"("key:value")的形式。type T struct {Name  string "json:Name"
}
$ go vet
# command-line-arguments
./main.go:8: struct field tag "json:Name" not compatible with reflect.StructTag.Get: bad syntax for struct tag value//JSON 标签的字段名 Name 是以大写字符开始的,这不符合 Go 语言的标准

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://xiahunao.cn/news/2906518.html

如若内容造成侵权/违法违规/事实不符,请联系瞎胡闹网进行投诉反馈,一经查实,立即删除!

相关文章

FMEA与智能机器人:提升机器人可靠性与安全性的关键

随着科技的飞速发展&#xff0c;智能机器人已经深入到我们生活的方方面面&#xff0c;从工业生产到家庭服务&#xff0c;从深海探险到太空探索&#xff0c;处处都有它们的身影。然而&#xff0c;随着应用的日益广泛&#xff0c;机器人系统的复杂性和不确定性也在增加&#xff0…

基于Springboot+Vue的酒店管理系统!新鲜出炉,可商用,带源码

新年了给大家分享一套基于SpringbootVue的酒店管理系统源码&#xff0c;在实际项目中可以直接复用。(免费提供&#xff0c;文末自取) 一、系统运行图&#xff08;管理端和用户端&#xff09; 1、管理登陆 2、房间管理 3、订单管理 4、用户登陆 5、房间预定 二、系统搭建视频教…

掌握html这一篇就够了

提示&#xff1a;文章写完后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录 前言一、HTML是什么&#xff1f;二、基础标签6个标题标签6级标题其他基础标签 8种文本标签6种表格标签4种表格标签基础标签修饰 4种媒体标签a标签img:图片audio&…

Vue中的一些指令与计算方法

语法 插值语法 HTML的双标签内容中使用&#xff0c;在{{}}之内书写JS代码 属性语法 1.v-bind或: 2.:属性名"值"或v-bind"值" 事件语法 v-on或 v-on:事件名"方法名"或事件名"方法名" 选项 选项&#xff1a;可选的配置项——官方…

Spring后置处理器(PostProcessor)

文章目录 引言BeanFactoryPostProcessor常见用法创建自定义后置处理器注册后置处理器执行后置处理器 BeanPostProcessor常见用法创建自定义后置处理器注册后置处理器执行后置处理器 实际需求验证配置文件的正确性检验逻辑 引言 在Spring框架中&#xff0c;后置处理器为我们提供…

鸿蒙开发第一节

一.开发准备-工具安装 1.鸿蒙开发官网&#xff1a;华为开发者联盟-智能终端能力开放,共建开发者生态 (huawei.com) 2.DevEco Studio3.1下载链接HUAWEI DevEco Studio和SDK下载和升级 | 华为开发者联盟 点击下载按钮进行下载2.1解压文件2.2双击运行此程序 2.3安装软件 点击N…

【JavaSE】java刷题——基础语法熟练应用

前言 通过本篇题目&#xff0c;可以让初学Java的小伙伴们更加熟练Java的基础语法~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 题1&#xff1a;数字9 出现的次数 题述&#xff1a;编写程序数一下 1到 100 的所有整数中…

fastapi学习记录

今天看了点fastap&#xff0c;简单记录下&#xff0c;fastapi是一个python下的后端框架。 参考学习网站菜鸟教程 安装 pip install fastapi pip install "uvicorn[standard]"安装好了以后就可以直接使用&#xff0c;最主要的使用方式就是写接口嘛&#xff0c;get&a…

状态压缩dp[详解 + 例题]

1 . 题目 2 . 分析 可以发现 : 横放的方案数 总方案数 ; 剩下的都是竖放去填补空缺 ; 关于状态定义 : 考虑按列拜访 &#xff0c; 某列的隔行用0/1表示摆放状态 ; 某行为1 : 表示横放 , 0 : 表示竖放 ; 状态表示 : f[i][j] : 表示拜访第i列&#xff0c;状态为j的方案数…

【八大排序】一篇文章搞定所有排序

文章目录 1.排序的概念2.常见排序算法的实现2.1 插入排序2.1.1直接插入排序2.1.2希尔排序 2.2选择排序2.2.1直接选择排序:2.2.2堆排序 2.3交换排序2.3.1冒泡排序2.3.2快速排序Hoare法前后指针法挖坑法非递归版本 2.4归并排序递归版本非递归版本 2.5计数排序3.排序的比较 1.排序…

报错 /core/library/think/cache/driver/File.php 第 126 行左右(已解决)

报错 /core/library/think/cache/driver/File.php 第 126 行左右 解决方法&#xff1a; 网站后台版本低于v1.5.2出现的缓存问题&#xff0c;如果无法登录后台了&#xff0c;就通过FTP&#xff0c;把 /data/runtime 里的都删掉&#xff0c;然后进后台升级到最新版 一、进入宝…

基于Python微博舆情数据爬虫可视化分析系统(NLP情感分析+爬虫+机器学习)

这里写目录标题 基于Python微博舆情数据爬虫可视化分析系统(NLP情感分析爬虫机器学习)一、项目概述二、微博热词统计析三、微博文章分析四、微博评论分析五、微博舆情分析六、项目展示七、结语 基于Python微博舆情数据爬虫可视化分析系统(NLP情感分析爬虫机器学习) 一、项目概…

疯狂数字直角三角形

上一篇文章的输出的数字直角三角形有个限制&#xff0c;就是边长n最大值为13&#xff0c;因为超过13最后就会输出3位数&#xff0c;这样斜边就不成一条直线了。 如果去掉这个限制呢&#xff1f;随便输入一个正整数&#xff08;int型&#xff09;&#xff0c;还能否输出这样的数…

【管理咨询宝藏59】某大型汽车物流战略咨询报告

本报告首发于公号“管理咨询宝藏”&#xff0c;如需阅读完整版报告内容&#xff0c;请查阅公号“管理咨询宝藏”。 【管理咨询宝藏59】某大型汽车物流战略咨询报告 【格式】PDF 【关键词】HR调研、商业分析、管理咨询 【核心观点】 - 重新评估和调整商业模式&#xff0c;开拓…

记一次 .NET某防伪验证系统 崩溃分析

一&#xff1a;背景 1. 讲故事 昨晚给训练营里面的一位朋友分析了一个程序崩溃的故障&#xff0c;因为看小伙子昨天在群里问了一天也没搞定&#xff0c;干脆自己亲自上阵吧&#xff0c;抓取的dump也是我极力推荐的用 procdump 注册 AEDebug 的方式&#xff0c;省去了很多沟通…

Linux离线安装mysql,node,forever

PS:本文是基于centos7实现的,要求系统能够查看ifconfig和unzip解压命令, 实现无网络可安装运行 首先现在百度网盘的离线文件包****安装Xftp 和 Xshell 把机房压缩包传到 home目录下****解压unzip 包名.zip 获取IP先获取到 linux 主机的ip ifconfig Xftp 连接输入IP,然后按照…

Nginx-记

Nginx是一个高性能的web服务器和反向代理服务器&#xff0c;用于HTTP、HTTPS、SMTP、POP3和IMAP协议。因它的稳定性、丰富的功能集、示例配置文件和低系统资源的消耗而闻名。 &#xff08;1&#xff09;更快 这表现在两个方面&#xff1a;一方面&#xff0c;在正常情况下&…

Go的数据结构与实现【Stack】

介绍 栈是存放值的一种特殊容器&#xff0c;在插入与删除值时&#xff0c;这种结构遵循后进先出&#xff08;Last-in-first-out&#xff0c;LIFO&#xff09;的原则&#xff0c;也就是说&#xff0c;值可以任意插入栈中&#xff0c;但每次取出的都是此前插入的最后一个值。 实…

STM32第十节(中级篇):EXTI(第一节)——EXTI功能框图及初始化结构体讲解(包括STM32中断应用总结)

目录 前言 STM32第十节&#xff08;中级篇&#xff09;&#xff1a;EXTI&#xff08;第一节&#xff09;——EXTI功能框图及初始化结构体讲解&#xff08;包括STM32中断应用总结&#xff09; EXTI功能框图 EXTI初始化结构体讲解 STM32中断应用总结 NVIC介绍 优先级 优先…

安卓Activity上滑关闭效果实现

最近在做一个屏保功能&#xff0c;需要支持如图的上滑关闭功能。 因为屏保是可以左右滑动切换的&#xff0c;内部是一个viewpager 做这个效果的时候&#xff0c;关键就是要注意外层拦截触摸事件时&#xff0c;需要有条件的拦截&#xff0c;不能影响到内部viewpager的滑动处理…