Golang Tag语法

439 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

Golang Tag语法

Tag格式

tag被定义在结构体字段的后面,以字符串的形式出现,如下所示:

type T struct {
	f1 string "f one"
	f2 string
	f3 string `f three`
	f4, f5 int64 `f four and five`
}

要注意,不管是双引号还是反引号,都可以用来当tag。如果结构体字段在定义的时候,两个字段共用一个属性,那么这个tag会被附在两个名字上,像上述代码中的f1,f5一样。

键值对

Tags可以由键值对来组成,通过空格符来分割键值 —key1:"value1" key2:"value2" key3:"value3"。如果Tags格式没问题的话,我们可以通过Lookup或者Get来获取键值对的值。 Lookup回传两个值,对应的值和是否找到。 Get只回传一个值,即对应的那个值,如果没有找到就返回空。

package main

import (
	"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.Lookup
	v, ok := f.Tag.Lookup("fruit")
	fmt.Printf("%s, %t\n", v, ok)

	// Tag.Get
	v = f.Tag.Get("fruit")
	fmt.Println(v)
}

运行结果:

fruit:"apple"
apple, true
apple

Tag的使用

json

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

package main

import (
	"encoding/json"
	"fmt"
)

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":"张三"}

ORM

ORM是指将关系型数据库中的记录映射为对象,以对象的形式展现。我们可以把对数据库的操作转化为对对象的操作。

面向对象的概念面向关系概念
对象表的行(记录)
属性表的列(字段)

对应到golang中,就是把对关系型数据库的操作转化为对结构体的操作。 我们以GORM框架来举例,在GORM中,与数据表进行映射的结构体我们称之为模型(Models)。

回归到Tag,在数据表中定义一个字段时,我们通常会在字段的末尾加上一些额外信息,比如约束、列大小等等。映射到Models中,就需要使用Tag来设置相应的信息。

例如下面这个Models:

type User struct {
  gorm.Model
  Name         string
  Age          sql.NullInt64
  Birthday     *time.Time
  Email        string  `gorm:"type:varchar(100);unique_index"`
  Role         string  `gorm:"size:255"` // 设置字段大小为255
  MemberNumber *string `gorm:"unique;not null"` // 设置会员号(member number)唯一并且不为空
  Num          int     `gorm:"AUTO_INCREMENT"` // 设置 num 为自增类型
  Address      string  `gorm:"index:addr"` // 给address字段创建名为addr的索引
  IgnoreMe     int     `gorm:"-"` // 忽略本字段
}

GORM框架支持很多结构体Tag,具体可以查看这篇博文:

blog.csdn.net/qq_49723651…