前端开发入门到精通的在线学习网站

网站首页 > 资源文章 正文

一文读懂Go结构体标签(go结构体默认值)

qiguaw 2024-10-24 12:59:49 资源文章 41 ℃ 0 评论


结构体标签定义

通过 reflect.Type 获取结构体成员信息 reflect.StructField 结构中的 Tag 被称为结构体标签(Struct Tag)。结构体标签是对结构体字段的额外信息标签。

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

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

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

key会指定反射的解析方式包含 json(JSON标签)、 orm(Beego标签)、gorm(GORM标签)、bson(MongoDB标签)、form(表单标签)、binding(表单验证标签).这些系统使用标签设定字段在处理时应该具备的特殊属性和可能发生的行为。这些信息都是静态的,无须实例化结构体,可以通过反射获取到。

json标签

JSON数组可以用于编码Go语言的数组和slice。

将Go语言中结构体slice转为JSON的过程叫编组(marshaling),编组通过json.Marshal函数完成。

如果在结构体slice编码成JSON的时候使用自定义的成员名,可以使用结构体成员Tag来实现。

示例:

type User1 struct {
	Name string `json:"username"` // 编码后的字段名为 username
	Age  int    `json:"userage"`  // 编码后的字段名为 userage
	Sex  string `json:"usersex"`  // 编码后的字段名为 usersex
}

type User2 struct {
	Name string `json:"username"`
	Age  int    `json:"userage"`
	Sex  string // 编码后的字段名为 Sex
}

type User3 struct {
	Name string `json:"username"`
	Age  int    `json:"-"` // 字段不进行序列化	Sex  string
}

func main() {
	u1 := User1{"ares", 20, "man"}
	jsondata1, err := json.Marshal(u1)
	if err != nil {
		fmt.Println("格式错误")
	} else {
		fmt.Printf("User1结构体转json:%s\n", jsondata1)
	}

	u2 := User2{"ares", 20, "man"}
	jsondata2, err := json.Marshal(u2)
	if err != nil {
		fmt.Println("格式错误")
	} else {
		fmt.Printf("User2结构体转json:%s\n", jsondata2)
	}

	u3 := User3{"ares", 20, "man"}
	jsondata3, err := json.Marshal(u3)
	if err != nil {
		fmt.Println("格式错误")
	} else {
		fmt.Printf("User3结构体转json:%s\n", jsondata3)
	}
}

输出为:

User1结构体转json:{"username":"ares","userage":20,"usersex":"man"}
User2结构体转json:{"username":"ares","userage":20,"Sex":"man"}
User3结构体转json:{"username":"ares","Sex":"man"}

"encoding/json"包的json.Marshal()方法作用就是把结构体转换为json,它读取了User结构体里面的标签,json键值对的键为定义的标签名,结构体的名字起了辅助作用,同时定义了字段数据类型。json.Unmarshal()可以把json字符串转换为结构体,在很多第三方包方法都会读取结构体标签。

标签选项


gorm标签

模型是标准的 struct,由基本数据类型以及实现了 Scanner 和 Valuer 接口的自定义类型及其指针或别名组成。
GORM 倾向于约定,而不是配置。默认情况下,GORM 使用 ID 作为主键,使用结构体名的 蛇形复数 作为表名,字段名的 蛇形 作为列名,并使用 CreatedAt、UpdatedAt 字段追踪创建、更新时间。
GORM 默认定义一个 gorm.Model 结构体,其包括字段 ID、CreatedAt、UpdatedAt、DeletedAt,可以嵌套入自建结构体,tag名大小写不敏感,建议使用camelCase风格,多个标签定义用分号(;)分隔:

// gorm.Model 的定义
type Model struct {
  ID        uint           `gorm:"primaryKey"`
  CreatedAt time.Time
  UpdatedAt time.Time
  DeletedAt gorm.DeletedAt `gorm:"index"`
}

建表示例:
结构体定义如下:

type AddUserAuth struct {
	gorm.BaseModel
	UUID        string `gorm:"column:user_uuid;comment:用户UUID;type:varchar(100);"`        // 用户UUID
	User        string `gorm:"column:user_name;comment:用户名称;type:varchar(50);"`           // 用户登录名
	Cluster     string `gorm:"column:cluster_name;comment:集群名称;type:varchar(50);"`     // k8s集群
	NameSpace   string `gorm:"column:namespace;comment:命名空间;type:varchar(50);"`      // 命名空间
	ServiceName string ` gorm:"column:service_name;comment:应用名称;type:varchar(50);"` // 应用名称
	ServiceType string `gorm:"column:service_type;comment:应用类型;type:varchar(50);"` // 应用类型
}

生成的建表语句如下:

CREATE TABLE `add_user_auths` (
  `id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
  `created_at` datetime DEFAULT NULL,
  `updated_at` datetime DEFAULT NULL,
  `deleted_at` datetime DEFAULT NULL,
  `user_uuid` varchar(100) DEFAULT NULL COMMENT '用户UUID',
  `user_name` varchar(50) DEFAULT NULL COMMENT '用户名称',
  `cluster_name` varchar(50) DEFAULT NULL COMMENT '集群名称',
  `namespace` varchar(50) DEFAULT NULL COMMENT '命名空间',
  `service_name` varchar(50) DEFAULT NULL COMMENT '应用名称',
  `service_type` varchar(50) DEFAULT NULL COMMENT '应用类型',
  PRIMARY KEY (`id`),
  KEY `idx_add_user_auths_deleted_at` (`deleted_at`)
) ENGINE=InnoDB AUTO_INCREMENT=8 DEFAULT CHARSET=utf8mb4

使用 GORM Migrator 创建表时,不会创建被忽略的字段。

如果想要保存 UNIX(毫/纳)秒时间戳,而不是 time,只需简单地将 time.Time 修改为 int 即可。

字段标签

声明 model 时,tag 是可选的,GORM 支持以下 tag:

关联标签

GORM 允许通过标签为关联配置外键、约束、many2many 表:


form标签

Gin中提供了模型绑定,将表单数据和模型进行绑定,方便参数校验和使用。

模型绑定:

// 表单数据
type LoginForm struct {
    UserName  string    `form:"username"`    
    Password  string    `form:"password"`
    Email	  string    `form:"email"`  
}
// model 或 service 层Model
type Email struct {
    Email       string
    Password    string
}


func EmailLogin (c *gin.Context) {
    var email LoginForm
    if err := c.ShouldBind(&email); err != nil {
        ...
    }
    // 获取表单数据局
    args := Email {
        Email:     email.Email,
        Password:  email.Password,
    }
    // 对参数进行后续使用
    ...

通过 form:"email" 对表单email数据进行绑定。然后通过Bind()、ShouldBind()等方法获取参数值。

binding标签

Gin 主要提供了两组绑定方法 Must bind 与 Should bind 。gin/binding 内置模型绑定实现,将请求数据提取到合适的绑定器。

Must bind:验证不通过,就会被终止或抛出特定的错误页面

Should bind:存在绑定错误,这个错误会被返回,需要自行处理相应的请求和错误。

Gin 框架本身已经实现了多种绑定,通常用来绑定来自请求数据,有不同的结构体实例与之对应。其实现的绑定有 JSON, XML, Form,Query,FormPost,FormMultipart,ProtoBuf,MsgPack,YAML,Uri。

Gin对于数据的校验使用的是 validator.v10 包,该包提供多种数据校验方法,通过binding:""标签来进行数据校验。

校验规则见github:https://github.com/go-playground/validator/blob/master/README.md

示例:

type LoginForm struct {
    Email     string    `form:"email" binding:"email"`    
    UserName  string    `form:"username" binding:"username"`    
    Password  string    `form:"password" binging:"required,min=6,max=10"`
}

特殊符号:


必须校验


字符串校验


范围校验

范围验证: 切片、数组和map、字符串,验证其长度;数值,验证大小范围。


字段校验

示例:

// 不同结构体校验
type S1 struct { 
    F1 string `validate:eqcsfield=S2.F2` 
    S2 struct { 
        F2 string 
    } 
}
// 同一结构体字段相同校验
type Email struct { 
    Email  string `validate:"lte=4"` 
    Pwd    string `validate:"min=10"` 
    Pwd2   string `validate:"eqfield=Pwd"`
}
// 同一结构体字段不相等
type User struct { 
    Name     string `validate:"lte=4"` 
    Age      int `validate:"min=20"` 
    Password string `validate:"min=10,nefield=Name"`
}

其他校验


ini标签

ini 是 Windows 上常用的配置文件格式, go-ini是 Go 语言中用于操作 ini 文件的第三方库。

若使用ini格式配置,需要将配置文件字段映射到结构体变量,如果键名与字段名不相同,那么需要在结构标签中指定对应的键名。标准库encoding/json、encoding/xml解析时可以将键名直接对应到字段名,而go-ini库不可以,所以需要在结构体标签指定对应键名。

示例:

## 配置文件 cnf.ini
user_name  = ares
age = 20


// 配置文件映射 结构体
type Config struct {
  UserName   string `ini:"user_name"`  // ini标签指定下键名
  Age  string `ini:"age"`
}

Tags:

本文暂时没有评论,来添加一个吧(●'◡'●)

欢迎 发表评论:

最近发表
标签列表