Go语言之 Struct Tag

在上一篇介绍Go反射的时候,提到了如何通过反射获取Struct的Tag,这一篇文章主要就是介绍这个的使用和原理,在介绍之前我们先看一下JSON字符串和Struct类型相互转换的例子。

JSON字符串对象转换
func main() {
    var u User
    h:=`{"name":"张三","age":15}`
    err:=json.Unmarshal([]byte(h),&u)    
    if err!=nil{
        fmt.Println(err)
    }else {
        fmt.Println(u)
    }}type User struct{
    Name string `name`
    Age int `age`}

上面这个例子就是Json字符串转User对象的例子,这里主要利用的就是User这个结构体对应的字段Tag,json解析的原理就是通过反射获得每个字段的tag,然后把解析的json对应的值赋给他们。

利用字段Tag不光可以把Json字符串转为结构体对象,还可以把结构体对象转为Json字符串。

 newJson,err:=json.Marshal(&u)
 fmt.Println((string(newJson)))

接着刚刚的例子,这样就可以转为一个新的字符串了,通过打印输出,可以看到和开始输入的字符串一样。

反射获取字段Tag

字段的Tag是标记到字段上的,所以我们可以通过先获取字段,然后再获取字段上的Tag。

func main() {
    var u User

    t:=reflect.TypeOf(u)    
    for i:=0;i<t.NumField();i++{
        sf:=t.Field(i)
        fmt.Println(sf.Tag)
    }}

获取字段上一篇我们提到过,获取字段后,调用.Tag就获取到对应的Tag字段了。

字段Tag的键值对

很多时候我们的一个Struct不止具有一个功能,比如我们需要JSON的互转、还需要BSON以及ORM解析的互转,所以一个字段可能对应多个不同的Tag,以便满足不同的功能场景。

Go Struct 为我们提供了键值对的Tag,来满足我们以上的需求。

func main() {
    var u User
    t:=reflect.TypeOf(u)    
    for i:=0;i<t.NumField();i++{
        sf:=t.Field(i)
        fmt.Println(sf.Tag.Get("json"))
    }}type User struct{
    Name string `json:"name"`
    Age int `json:"age"`}

以上的例子,使用了键值对的方式配置Struct Tag,Key-Value以冒号分开,这里的Key为json,所以我们可以通过这个Key获取对应的值,也就是通过.Tag.Get("json"))方法。Get方法就是通过一个Key获取对应的tag设置。

除此之外,我们还可以设置多个Key,来满足我们上面说的场景。

func main() {
    var u User
    t:=reflect.TypeOf(u)    
    for i:=0;i<t.NumField();i++{
        sf:=t.Field(i)
        fmt.Println(sf.Tag.Get("json"),",",sf.Tag.Get("bson"))
    }}type User struct{
    Name string `json:"name" bson:"b_name"`
    Age int `json:"age" bson:"b_age"`}

多个Key使用空格进行分开,然后使用Get方法获取不同Key的值。

Struct Tag可以提供字符串到Struct的映射能力,以便我们作转换,除此之外,还可以作为字段的元数据的配置,提供我们需要的配置,比如生成Swagger文档等。

时间: 2024-10-08 19:13:21

Go语言之 Struct Tag的相关文章

c语言之struct

1. 结构的基础知识 跟数组一样是成员的集合,但与数组有很大的区别,结构的元素不能通过下标法来访问,因为各个成员的大小可能不同,但是数组可以,因为数组元素保持一致. 1.1 结构声明 struct  tag {member-list } variable-list ; 上面黑色部分是可选部分,但是必须同时出现两个. 实例一:下面是实例: struct{ int a ; char b ; float c ; }x,y[20],*z; 上面定义了实例化了x,y[20],*z ; x是结构变量,y是结

【linux】U-BOOT与linux kernel通信: struct tag

  欢迎转载,转载时需保留作者信息. 邮箱:[email protected] 博客园地址:http://www.cnblogs.com/embedded-tzp Csdn博客地址:http://blog.csdn.net/xiayulewa     u-boot与linux通信格式       如上图,开机时执行u-boot, u-boot引导完后,就是交给linux系统了,但是linux需要一些基本信息,如内存大小,启动方式等,这就涉及到u-boot和linux通信. 而通信格式由linux

C语言的struct/union字节对齐

C语言的一大优势就是对内存空间的控制,当然,一般情况下对于开发人员来说都是透明的.看一个始终困扰初学者的问题:字节对齐! 先看四个重要的基本概念:1.数据类型自身的对齐值:对于char型数据,其自身对齐值为1,对于short型为2,对于int,float,double类型,其自身对齐值为4,单位字节. 2.结构体或者类的自身对齐值:其成员中自身对齐值最大的那个值. 3.指定对齐值:#pragma pack (value)时的指定对齐值value. 4.数据成员.结构体和类的有效对齐值:自身对齐值

C语言typedef struct具体解释

在C中定义一个结构体要用typedef,如: typedef struct Student { int a; }Stu; 于是在声明变量的时候就能够:Stu stu1;(假设没有typedef就必须用struct Student stu1;来声明).这里的Stu实际上就是struct Student的别名:Stu == struct Student. 当然事实上这里能够不写Student,例如以下: typedef struct { int a; }Stu; 这里也就必须使用Stu stu1来声

Go 语言之 struct 结构体

struct 结构 Go中的struct与C语言中的struct非常相似,并且Go没有class 使用type<Name> struct{} 定义结构,名称遵循可见性规则 支持指向自身的指针类型成员 支持匿名结构,可用作成员或定义成员变量 匿名结构也可以用于map的值 可以使用字面值对结构进行初始化 允许直接通过指针来读写结构成员 相同类型的成员可以进行直接拷贝赋值 支持== 与 != 比较运算符,但不支持 > 或 < 支持匿名字段,本质上是定义了以某个类型名为名称的字段 嵌入结构

C语言复杂struct类型get或者set字段的简化方法

p.p1 { margin: 0.0px 0.0px 0.0px 0.0px; font: 12.0px ".PingFang SC"; color: #454545 } span.s1 { font: 12.0px "Helvetica Neue" } 今天学习librdkafka的conf配置相关的代码,学到了一个C语言代码编写的技巧.作者真的是把C语言用得出神入化. 我们平时编写C语言代码,经常会用struct类型来模拟面向对象中的class.比如我实现了下面

c语言关键字-struct,union,enum及柔性数组

一.struct关键字与柔性数组 c语言中的struct可以看做变量的集合,struct中的每个数据成员都有独立的存储空间 柔性数组:柔性数组在C99中也称之为伸缩型数组,是C99的扩展,简言之就是struct结构里的标识占位符(不占用struct的空间),柔性数组的结构只能在堆上生成. 声明柔性数组的规则 柔性数组成员必须为结构(struct)中的最后一个成员 结构中至少有一个其他成员 柔性数组就像普通数组一样被声明,除了它的方括号内为空 1 struct softarry 2 { 3 int

C语言 typedef struct

结构体typedef struct的用法 和结构体的定义 结构体的定义: 1. struct Person { char name[20]; char sex; float  height; int age; };   只有结构体的定义 2. struct Person { char name[20]; char sex; float  height; int age; } xiaohong;  附加该结构体类型的“结构体变量”的初始化定义结构体 这种定义就相当于 struct Person {

go语言学习 ---struct 对象的序列化和反序列化(xml)

实例1: //main package main import ( "encoding/xml" "fmt" ) type person struct { Name string Age int } func main() { p := person{Name: "sary", Age: 20} if data, err := xml.MarshalIndent(p, "", " "); err != ni