在学习之初我们会发现创建一个struct来表示一个model是很正常的事情,特别是在序列化json的时候,在这个学些过程中我们会发现一个内容就是跟在每个struct成员后面的用单引号标示的内容,我们称之为Struct Tag,它其实有很灵活的用途,但它的用途可以归纳为标记和扩展。
为了很好的理解Tag的一些用法,将从最原理的一些部分开始,比如它是怎么定义的,怎么工作的,怎么使用的,到最后我们要如何去用。其中我会拿开源项目gorm 来做事例,因为ORM最重要的部分影射和定义就是靠Tag来完成的
Struct Tag是存在于Struct下面成员的附加属性,它的定义永远都是以key-value的形式出现的,多个定义的情况下以空格分割
在StructTag的应用中,使用最多的就是json的序列化了,序列化的包会读取tag内容,对json结果进行重命名输出,那么它是怎么读取到的呢?我们需要先了解这个Tag在整个语言段落处于什么层次。
如果直接拿到了这串文本我们可以这样做
package main
import (
"fmt"
"reflect"
)
func main() {
// 使用reflect.StructTag解析这段文本的tag内容
tag := reflect.StructTag(`json:"foo,omitempty" xml:"foo"`)
// 直接使用Get获取json定义
value := tag.Get("json")
fmt.Printf("value: %q\n", value)
}
比如定义了一个车辆的model,给它增加了一些json的tag项
type Vehicle struct {
ID int `json:"id"`
CityName string `json:"city_name"`
Provider string `json:"provider"`
PlateNumber string `json:"plate_number"`
MaxPeople int64 `json:"max_people"`
PowerType string `json:"power_type"`
}
通过reflect反射机制也可以获取到这个结构体的tag内容,比如以下代码
reflectType := reflect.ValueOf(Vehicle{}).Type()
fmt.Printf("fields number: %v\n", reflectType.NumField())
for i := 0; i < reflectType.NumField(); i++ {
fmt.Printf("%v", reflectType.Field(i).Name)
fmt.Printf(" tag:%v\n", reflectType.Field(i).Tag.Get("json"))
}
执行过后的结果,清清楚楚的取得了tag的内容
实际应用场景中,我们除了经常对json序列化用到以外,还经常在使用开源组件中遇到,比如说GORM,它是一个典型的应用场景,因为它需要对实体中的每一项进行额外定义,以达到映射和功能标记的作用。虽然查看它的官方文档,我们可以很详细的知道用法,我们也可以直接跳到GORM的Github仓库去了解它是如何运作的。
进入model_struct.go文件,在GetModelStruct方法中我们可以看到
//通过反射获取类型定义
reflectType := reflect.ValueOf(scope.Value).Type()
for reflectType.Kind() == reflect.Slice || reflectType.Kind() == reflect.Ptr {
reflectType = reflectType.Elem()
}
.......
// 对每一项进行tag的获取和逻辑
// Get all fields
for i := 0; i < reflectType.NumField(); i++ {
if fieldStruct := reflectType.Field(i); ast.IsExported(fieldStruct.Name) {
......
field.TagSettingsGet("PRIMARY_KEY")
......
if value, ok := field.TagSettingsGet("COLUMN"); ok {
field.DBName = value
} else {
field.DBName = ToColumnName(fieldStruct.Name)
}
......
整个GORM的核心就在于根据数据库映射的model,然后再根据定义好的内部结构来拼接sql达到ORM的效果。这里跟dotnet里面的Attribute的作用类似,我们做了一些Attribute也可以通过反射获取信息。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。
原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。
如有侵权,请联系 cloudcommunity@tencent.com 删除。