当前位置 : 主页 > 网络编程 > PHP >

Golang结构体中Tag的使用

来源:互联网 收集:自由互联 发布时间:2023-10-08
Golang中可以为结构体的字段添加tag,这类似于Java中为类的属性添加的注解,Golang本身的encoding/json包解析json使用了tag,一些开源的ORM框架,也广泛使用了tag,那么,我们如何通过代码自


Golang中可以为结构体的字段添加tag,这类似于Java中为类的属性添加的注解,Golang本身的encoding/json包解析json使用了tag,一些开源的ORM框架,也广泛使用了tag,那么,我们如何通过代码自己实现tag的解析,从而简化结构体字段的使用方式呢?下面看一个例子。

假设有一个Person结构体定义如下

type Person struct {
Name string `label:"Person Name: " uppercase:"true"`
Age int `label:"Age is: "`
Sex string `label:"Sex is: "`
Description string
}

有四个字段,字段后面的使用​​...​​引用的部分就是tag,我们希望使用一个名为lable的tag来定义打印时候的标题,默认使用字段名称加冒号作为label。如果是字符串类型的字段,通过名称为uppercase的tag控制是否显示字符串的大写形式,默认按照小写。例如有一个Person结构体变量为

{Tom 29 Male Cool}

按照上面Person中tag的使用,打印应该为

Person Name: TOM

Age is: 29

Golang解析标签主要通过反射实现,下面就看看我们如何实现上面的功能:

package main

import (
"fmt"
"reflect"
"strings"
)

type Person struct {
Name string `label:"Person Name: " uppercase:"true"`
Age int `label:"Age is: "`
Sex string `label:"Sex is: "`
Description string
}

// 按照tag打印结构体
func PrintUseTag(ptr interface{}) error {

// 获取入参的类型
t := reflect.TypeOf(ptr)

// 入参类型校验
if t.Kind() != reflect.Ptr || t.Elem().Kind() != reflect.Struct {
return fmt.Errorf("参数应该为结构体指针")
}

// 取指针指向的结构体变量
v := reflect.ValueOf(ptr).Elem()

// 解析字段
for i := 0; i < v.NumField(); i++ {

// 取tag
fieldInfo := v.Type().Field(i)
tag := fieldInfo.Tag

// 解析label tag
label := tag.Get("label")
if label == "" {
label = fieldInfo.Name + ": "
}

// 解析uppercase tag
value := fmt.Sprintf("%v", v.Field(i))
if fieldInfo.Type.Kind() == reflect.String {
uppercase := tag.Get("uppercase")
if uppercase == "true" {
value = strings.ToUpper(value)
} else {
value = strings.ToLower(value)
}
}

fmt.Println(label + value)
}

return nil
}

func main() {
person := Person{
Name: "Tom",
Age: 29,
Sex: "Male",
Description: "Cool",
}

PrintUseTag(&person)
}

上面代码,main函数创建了一个名为person的Person结构体变量,然后调用PrintUseTag函数进行打印,所以主要的逻辑我们要看PrintUseTag函数。该函数通过反射,获取tag,然后按照不同的情况解析tag并执行不同的操作,只有字段类型为字符串时候,我们才去判断uppercase tag是否使用,之后打印每一个字段的label和value组成的字符串。value不一定都是字符串类型,所以我们借助于fmt包的Sprintf函数的%v,将其他类型转化为字符串表述。

掌握了tag的使用,我们可以使用Golang定义自己的很多工具tag,减少代码量,尤其在定义一些框架时作用更加明显。


上一篇:【Web技术】247-Web登录其实没那么简单
下一篇:没有了
网友评论