Go语言struct要使用 tags的原因解析

news2024/10/7 11:30:22

这篇文章主要介绍了为什么 Go 语言 struct 要使用 tags,在本文中,我们将探讨为什么 Go 语言中需要使用 struct tags,以及 struct tags 的使用场景和优势,需要的朋友可以参考下

在 Go 语言中,struct 是一种常见的数据类型,它可以用来表示复杂的数据结构。在 struct 中,我们可以定义多个字段,每个字段可以有不同的类型和名称。

除了这些基本信息之外,Go 还提供了 struct tags,它可以用来指定 struct 中每个字段的元信息。

在本文中,我们将探讨为什么 Go 语言中需要使用 struct tags,以及 struct tags 的使用场景和优势。

struct tags 的使用

struct tags 使用还是很广泛的,特别是在 json 序列化,或者是数据库 ORM 映射方面。

 

在定义上,它以 key:value 的形式出现,跟在 struct 字段后面,除此之外,还有以下几点需要注意:

使用反引号

在声明 struct tag 时,使用反引号 ` 包围 tag 的值,可以防止转义字符的影响,使 tag 更容易读取和理解。例如:

1

2

3

4

5

type User struct {

    ID    int    `json:"id" db:"id"`

    Name  string `json:"name" db:"name"`

    Email string `json:"email" db:"email"`

}

避免使用空格

在 struct tag 中,应该避免使用空格,特别是在 tag 名称和 tag 值之间。使用空格可能会导致编码或解码错误,并使代码更难以维护。例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

// 不规范的写法

type User struct {

    ID    int    `json: "id" db: "id"`

    Name  string `json: "name" db: "name"`

    Email string `json: "email" db: "email"`

}

// 规范的写法

type User struct {

    ID    int    `json:"id" db:"id"`

    Name  string `json:"name" db:"name"`

    Email string `json:"email" db:"email"`

}

避免重复

在 struct 中,应该避免重复使用同一个 tag 名称。如果重复使用同一个 tag 名称,编译器可能会无法识别 tag,从而导致编码或解码错误。例如:

1

2

3

4

5

6

7

8

9

10

11

12

13

// 不规范的写法

type User struct {

    ID    int    `json:"id" db:"id"`

    Name  string `json:"name" db:"name"`

    Email string `json:"email" db:"name"`

}

// 规范的写法

type User struct {

    ID    int    `json:"id" db:"id"`

    Name  string `json:"name" db:"name"`

    Email string `json:"email" db:"email"`

}

使用标准化的 tag 名称

为了使 struct tag 更加标准化和易于维护,应该使用一些标准化的 tag 名称。

例如,对于序列化和反序列化,可以使用 jsonxmlyaml 等;对于数据库操作,可以使用 db

1

2

3

4

5

6

type User struct {

    ID       int    `json:"id" db:"id"`

    Name     string `json:"name" db:"name"`

    Password string `json:"-" db:"password"` // 忽略该字段

    Email    string `json:"email" db:"email"`

}

其中,Password 字段后面的 - 表示忽略该字段,也就是说该字段不会被序列化或反序列化。

多个 tag 值

如果一个字段需要指定多个 tag 值,可以使用 , 将多个 tag 值分隔开。例如:

1

2

3

4

5

type User struct {

    ID        int    `json:"id" db:"id"`

    Name      string `json:"name" db:"name"`

    Email     string `json:"email,omitempty" db:"email,omitempty"`

}

其中 omitempty 表示如果该字段值为空,则不序列化该字段。

struct tags 的原理

Go 的反射库提供了一些方法,可以让我们在程序运行时获取和解析结构体标签。

介绍这些方法之前,先来看看 reflect.StructField ,它是描述结构体字段的数据类型。定义如下:

1

2

3

4

5

type StructField struct {

    Name      string      // 字段名

    Type      Type        // 字段类型

    Tag       StructTag   // 字段标签

}

结构体中还有一些其他字段,被我省略了,只保留了和本文相关的。

在结构体的反射中,我们经常使用 reflect.TypeOf 获取类型信息,然后使用 Type.Field 或 Type.FieldByName() 获取结构体字段的 reflect.StructField,然后根据 StructField 中的信息做进一步处理。

例如,可以通过 StructField.Tag.Get 方法获取结构体字段的标签值。

下面看一段代码:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

package main

import (

    "fmt"

    "reflect"

)

type User struct {

    Name string `json:"name"`

    Age  int    `json:"age"`

}

type Manager struct {

    Title string `json:"title"`

    User

}

func main() {

    m := Manager{Title: "Manager", User: User{Name: "Alice", Age: 25}}

    mt := reflect.TypeOf(m)

    // 获取 User 字段的 reflect.StructField

    userField, _ := mt.FieldByName("User")

    fmt.Println("Field 'User' exists:", userField.Name, userField.Type)

    // 获取 User.Name 字段的 reflect.StructField

    nameField, _ := userField.Type.FieldByName("Name")

    tag := nameField.Tag.Get("json")

    fmt.Println("User.Name tag:", tag)

}

运行以上代码,输出结果如下:

Field 'User' exists: User {string int}
User.Name tag: "name"

struct tags 的优势

使用 struct tag 的主要优势之一是可以在运行时通过反射来访问和操作 struct 中的字段。

比如在 Go Web 开发中,常常需要将 HTTP 请求中的参数绑定到一个 struct 中。这时,我们可以使用 struct tag 指定每个字段对应的参数名称、验证规则等信息。在接收到 HTTP 请求时,就可以使用反射机制读取这些信息,并根据信息来验证参数是否合法。

另外,在将 struct 序列化为 JSON 或者其他格式时,我们也可以使用 struct tag 来指定每个字段在序列化时的名称和规则。

此外,使用 struct tag 还可以提高代码的可读性和可维护性。在一个大型的项目中,struct 中的字段通常会包含很多不同的元信息,比如数据库中的表名、字段名、索引、验证规则等等。

如果没有 struct tag,我们可能需要将这些元信息放在注释中或者在代码中进行硬编码。这样会让代码变得难以维护和修改。而使用 struct tag 可以将这些元信息与 struct 字段紧密关联起来,使代码更加清晰和易于维护。

常用的 struct tags

在 Go 的官方 wiki 中,有一个常用的 struct tags 的库的列表,我复制在下面了,感兴趣的同学可以看看源码,再继续深入学习。

TagDocumentation
xmlxml package - encoding/xml - Go Packages
jsonjson package - encoding/json - Go Packages
asn1asn1 package - encoding/asn1 - Go Packages
reformreform package - gopkg.in/reform.v1 - Go Packages
dynamodbdynamodbattribute - Amazon Web Services - Go SDK
bigquerybigquery package - cloud.google.com/go/bigquery - Go Packages
datastoredatastore package - cloud.google.com/go/datastore - Go Packages
spannerspanner package - cloud.google.com/go/spanner - Go Packages
bsonbson package - labix.org/v2/mgo/bson - Go Packages, bsoncodec package - go.mongodb.org/mongo-driver/bson/bsoncodec - Go Packages
gormgorm package - github.com/jinzhu/gorm - Go Packages
yamlyaml package - gopkg.in/yaml.v2 - Go Packages
tomltoml package - github.com/pelletier/go-toml - Go Packages
validateGitHub - go-playground/validator: :100:Go Struct and Field validation, including Cross Field, Cross Struct, Map, Slice and Array diving
mapstructuremapstructure package - github.com/mitchellh/mapstructure - Go Packages
parserparticiple package - github.com/alecthomas/participle - Go Packages
protobufGitHub - golang/protobuf: Go support for Google's protocol buffers
dbGitHub - jmoiron/sqlx: general purpose extensions to golang's database/sql
urlGitHub - google/go-querystring: go-querystring is Go library for encoding structs into URL query strings.
featureGitHub - nikolaydubina/go-featureprocessing: 🔥 Fast, simple sklearn-like feature processing for Go

以上就是本文的全部内容,如果觉得还不错的话欢迎点赞,转发和关注,感谢支持。

到此这篇关于为什么 Go 语言 struct 要使用 tags的文章就介绍到这了。

点击拿去
50G+学习视频教程
100+Python初阶、中阶、高阶电子书籍

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/742523.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

由于找不到vcomp100.dll,无法继续执行代码,解决方法

为什么会由于找不到vcomp100.dll,无法继续执行代码问题呢? 文件被误删除:有时候,在进行系统清理或卸载应用程序时,可能会不小心删除了vcomp100.dll文件。如果某个程序依赖于该文件,并且文件被删除,那么该程…

ESP32开发:IDFV4.4配置LVGL8.3

配置LVGL8.3源码 LVGL GITHUB代码仓库如下:https://github.com/lvgl/lvgl/tree/release/v8.3 官方已经在ESP32上移植好的代码demo,目前最新版是LVGL 7.9:https://github.com/lvgl/lv_port_esp32 我们可以将LVGL官方配置好的ESP32 LVGL仓库下…

超详细的学习笔记:CSS盒子模型(附代码示例)

目录 一、CSS三大特性 1、继承性 2、层叠性 3、优先级 4、权重叠加的计算 二、PxCook的基本使用 三、盒子模型 1、盒子模型的介绍 2、内容的宽度和高度 3、边框 (border) 1、连写形式 2、单方向设置 3、单个属性 8、内边距(padding)和外边…

arm学习stm32之spi总线数码管倒计时

由于时间没有用时间计时器操作&#xff0c;有些误差&#xff0c;后续有空会翻新计时器版本 main.c #include "spi.h" extern void printf(const char *fmt, ...); void delay_ms(int ms) {int i,j;for(i 0; i < ms;i)for (j 0; j < 1800; j); } int num[10…

钉钉提示 redirect_url的域名不在appid的安全域名内

钉钉提示 redirect_url的域名不在appid的安全域名内 1、需要在《钉钉开放平台》- 开发者后台设置《钉钉扫码登陆功能》 2、如果钉钉界面没有钉钉扫码登陆功能-》点击浏览器右下角-》《返回旧版》 3、备注&#xff1a;当前访问的IP地址跟钉钉扫码登陆功能填写的IP地址需保持一致…

代码审计工具Fortify基本使用

最近接触到一款代码审计的工具 — Fortify SCA and Applications 22.2.0&#xff0c;现就其基本使用做一简单介绍&#xff01; Fortify是一个应用安全测试软件&#xff0c;是Micro Focus旗下AST&#xff08;应用程序安全测试&#xff09;产品。 Fortify能够提供静态和动态应用…

Acwing 853.有边数限制的最短路

Acwing 853.有边数限制的最短路 链接:853. 有边数限制的最短路 - AcWing题库 /* 题解:bellman_ford算法 可以算是一种暴力的算法了 他可以解决有复权边的单源最短路径 也可以解决图是否存在负环的问题 还可以求出 不超过k条边的最短路径问题 但是效率低下 时间复杂度为o(nk)n…

超有趣的linux命令2

超有趣的linux命令2 此次实验命令均在Ubuntu16.04版本上测试 注意有些命令需要在图形化界面才能显示效果 温馨提示&#xff1a;可能有人是第一次接触Ubuntu&#xff0c;所以下面详细写了如何配置源和网络&#xff0c;以及安装命令的方式 1. 首先配置软件源 以命令行方式配置…

Comate代码助手推出,现场生成了贪吃蛇游戏,我们距离AI自动编程还有多远?

Comate代码助手推出&#xff0c;现场生成了贪吃蛇游戏&#xff0c;我们距离AI自动编程还有多远&#xff1f; 百度智能云推出“Comate”代码助手&#xff0c;并正式开放邀测&#xff0c;不算很意外。 毕竟让AI写代码&#xff0c;跑一跑贪吃蛇&#xff0c;算是传统艺能。 不过你…

MongoDB 简介及安装(windows环境下)

一、MongoDB 简介 1、MongoDB 是什么 MongoDB 是一个开源的、基于分布式的、面向文档存储的非关系型数据库。是非关系型数据库当中功能最丰富、最像关系数据库的。 MongoDB 将数据存储为一个文档&#xff0c;数据结构由键值(key>value)对组成。MongoDB 文档类似于 JSON 对…

API全场景零码测试机器人——ATGen带来“超自动化”测试模式

HDC期间可参与新手入驻华为云Testplan抽奖活动&#xff0c;活动链接在文末 众所周知&#xff0c;软件服务及组件之间的交互主要依赖大量的API接口。以华为云300多个商用云服务为例&#xff0c;平均每个服务含500接口&#xff0c;接口总数高达10万&#xff0c;接口调用上下文业务…

[GWCTF 2019]babyvm 题解

虚拟机 这是一个虚拟机的题目 上图是虚拟机的执行流程&#xff0c;Dispatcher(分发器)读取Opcode&#xff08;虚拟机操作码&#xff09; 然后根据操作码进行跳转执行 所以做这道虚拟机的题&#xff0c;我们就要找到操作码 并且明白操作码对应的含义 然后对操作码进行一句一…

MySQL整合篇(SQL语句执行流程-->索引篇-->事务篇-->锁篇)

MySQL 基础篇 1.1 执行一条SQL语句会发生什么 1. MySQL架构一共分为两层 server 和 存储引擎层&#xff08;一般为Innodb引擎&#xff09; 主要执行流程都在server层&#xff1a;连接器&#xff0c;查询缓存&#xff0c;解析SQL&#xff08;解析器&#xff09;&#xff0c;执行…

MySQL存储函数和存储过程习题

创建表并插入数据 字段名 数据类型 主键 外键 非空 唯一 自增id INT 是 否 是 是 否name VARCHAR(50) 否 否 是 否 否glass VARCHAR(50) 否 否 是 否 否sch 表内容id name glass1 xiaommg glass 12 xiaojun glass 21、创建一个可以统计…

零代码编程:用ChatGPT批量识别图片PDF中的文字

有些PDF页面是图片格式&#xff0c;要怎么批量把图片中的文字识别出来&#xff1f;借助ChatGPT可以轻松完成这个任务。 首先要安装一些相关的软件和Python库。 安装tesseract-ocr&#xff08;OCR&#xff09;软件&#xff0c;最新版的是tesseract-ocr-w64-setup-v5.3.0.20221…

BP神经网络数据分类——语音特征信号分类(Matlab代码实现)

目录 &#x1f4a5;1 概述 &#x1f4da;2 运行结果 &#x1f389;3 参考文献 &#x1f468;‍&#x1f4bb;4 Matlab代码 &#x1f4a5;1 概述 BP神经网络是一种常见的人工神经网络&#xff0c;用于数据分类和回归等任务。在语音特征信号分类中&#xff0c;BP神经网络可…

ANSI转义码sehll演示脚本

ANSI转义码是我在修改文字颜色的时候了解的&#xff0c;以下是我翻译的一个shell小程序的画面 原文在此 他使用c写的&#xff0c;我调整了一下&#xff0c;用shell改写了一个 这是上传的脚本文件&#xff0c;设置的是免费的&#xff0c;可以下载看看玩玩 (3条消息) 【免费】A…

Android Java代码与JNI交互基础数据类型转换(三)

🔥 Android Studio 版本 🔥 🔥 基础类型数据的转换 🔥 定义传递基础数据类型到JNI的函数 package com.cmake.ndk1.jni;public class JNIBasicType{static{System.loadLibrary("native-lib");}public native int callNativeInt(int num);public native byte …

javascript-正则表达式匹配出URL地址,批量添加a标签

一开始接到这个需求觉得简单&#xff0c;结果越搞越复杂&#xff0c;反复了很多次&#xff0c;没有特别好的解决方案 最近接到一个需求&#xff0c;客服输入框需要将发送出去的消息中含有url地址匹配出来添加上a标签&#xff0c;但是由于输入框是富文本&#xff0c;所以输入框内…

优秀的 RocketMQ 可视化管理工具 GUI 客户端

优秀的 RocketMQ 可视化管理工具 GUI 客户端 官网地址&#xff1a;http://www.redisant.cn/rocketmq 快速查看所有 RocketMQ 集群&#xff0c;包括Brokers、Topics和Consumers查看消费者订阅了哪些主题&#xff0c;以及消息队列被分配给了哪些消费者&#xff1b;当出现消息积…