GO语言入门-反射5(结构体的Tag)
12.5 结构体的 Tag
在定义结构体类型时,可以在字段后面加上一个字符串,称为 Struct Tag。Tag 主要用来补充附加信息。
Tag 由多个 key - value 构成,并以空格来分隔,key 和 value 之间用英文的冒号分隔。其格式如下:
key1:"value1" key2:"value2" key3:"value3"……
value 必须放在一对双引号中。为了避免字符转义,Tag 字符串可以用 “`” 字符来包装,就像下面这样:
key1:"value1" key2:"value2" key3:"value3"
在 reflect 包中定义了 StructTag 类型,表示 Tag 实例。
type StructTag string
从定义上可以看出,StructTag 是以字符串为基础的新类型。为了便于访问 Tag 中的条目,StructTag 类型提供以下两个方法:
- Get:根据 key 获取对应的 value。
- Lookup:根据 key 查找 value。如果找到,返回值 ok 为 true,并将结果存到 value 中;如果找不到,则 ok 为 false。
下面的示例演示了如何通过字段的 Tag 来为用户名和密码设置限制条件。当程序对用户信息进行检查时,会从 Tag 中读出相应的限制条件,如果所设置的用户名和密码与限制条件不符,则会输出错误信息。
步骤 1: 定义 User 结构体
type User struct {Username string `maxlen:"10"`Password string `minlen:"8" mask:"* "`
}
在 Username 字段的 Tag 中,maxlen 表示用户名的最大长度为 10 个字符,同样,在 Password 字段的 Tag 中,minlen 表示密码的最小长度为 8 个字符。mask 指定密码的掩码,掩码用于在屏幕输出密码时隐藏真实的密码内容,输出形如 “*****” 的文本。
步骤 2: 定义 validateUser 函数,用于检查用户名和密码是否满足限制条件
func validateUser(u User) {var typofUser = reflect.TypeOf(u)var valofUser = reflect.ValueOf(u)// 读出 TagtagUn := typofUser.Field(0).TagtagPwd := typofUser.Field(1).Tag// 解析用户名最大长度maxLenofUn, _ := strconv.ParseInt(tagUn.Get("maxlen"), 10, 0)// 解析密码最小长度minLenofPwd, _ := strconv.ParseInt(tagPwd.Get("minlen"), 10, 0)// 读取两个字段的值var usrName = valofUser.Field(0).String()var pssWd = valofUser.Field(1).String()// 开始验证unLen := utf8.RuneCountInString(usrName)pwdLen := utf8.RuneCountInString(pssWd)if unLen > int(maxLenofUn) {fmt.Printf("用户名 %s 长度超过 %d\n", usrName, maxLenofUn)return}if pwdLen < int(minLenofPwd) {// 获取密码掩码maskChar := tagPwd.Get("mask")// 生成类似"* * * * * * * *"的密码字符串displayPwd := strings.Repeat(maskChar, pwdLen)fmt.Printf("密码 %s 的长度不符,至少需要 %d 个字符\n", displayPwd, minLenofPwd)return}fmt.Println("用户信息符合要求")
}
步骤 3: 创建第一个 User 实例,并为字段赋值,然后调用 validateUser 函数进行检查
var u1 User
u1.Username = "jk_056546595xlase"
u1.Password = "65656565656"
validateUser(u1)
u1 对象设置的用户名过长,检查结果为:
用户名 jk_056546595xlase 长度超过10
步骤 4: 创建第二个 User 实例,并为字段赋值,然后进行检查
var u2 User
u2.Username = "Jack"
u2.Password = "321"
validateUser(u2)
u2 对象的密码长度不符合要求,检查结果为:
密码 *** 的长度不符,至少需要8个字符
步骤 5: 创建第三个 User 实例,并为字段赋值,然后进行检查
var u3 User
u3.Username = "Alice"
u3.Password = "UUI9ocg210359m82"
validateUser(u3)
u3 对象完全满足限制条件的要求,所以顺利通过检查。
补充:
在Go语言里,结构体标签(Tag)是依附于结构体字段的元数据字符串,它能为字段增添额外信息,这些信息可在运行时借助反射机制读取,从而实现序列化、数据验证、数据库映射等多种功能。
代码示例
下面的示例代码会展示结构体标签在JSON序列化、数据验证以及自定义业务逻辑中的应用。
package mainimport ("encoding/json""fmt""reflect""strconv""strings"
)// User 定义用户结构体,包含多个带标签的字段
type User struct {// JSON序列化标签,指定JSON键名及忽略空值Name string `json:"user_name,omitempty" validate:"min=3,max=20" biz:"name"`Age int `json:"user_age" validate:"min=18,max=100" biz:"age"`Email string `json:"user_email" validate:"email" biz:"email"`Password string `json:"-" validate:"min=6" biz:"password"`
}// validate 自定义验证函数,根据标签规则验证结构体字段
func validate(u interface{}) error {v := reflect.ValueOf(u)if v.Kind() == reflect.Ptr {v = v.Elem()}t := v.Type()for i := 0; i < v.NumField(); i++ {field := t.Field(i)tag := field.Tag.Get("validate")if tag == "" {continue}rules := strings.Split(tag, ",")value := v.Field(i)switch value.Kind() {case reflect.String:strValue := value.String()for _, rule := range rules {parts := strings.Split(rule, "=")if len(parts) == 2 {key, val := parts[0], parts[1]switch key {case "min":min, _ := strconv.Atoi(val)if len(strValue) < min {return fmt.Errorf("%s 长度不能小于 %d", field.Name, min)}case "max":max, _ := strconv.Atoi(val)if len(strValue) > max {return fmt.Errorf("%s 长度不能大于 %d", field.Name, max)}case "email":if !strings.Contains(strValue, "@") {return fmt.Errorf("%s 不是有效的邮箱地址", field.Name)}}}}case reflect.Int:intValue := value.Int()for _, rule := range rules {parts := strings.Split(rule, "=")if len(parts) == 2 {key, val := parts[0], parts[1]switch key {case "min":min, _ := strconv.Atoi(val)if intValue < int64(min) {return fmt.Errorf("%s 不能小于 %d", field.Name, min)}case "max":max, _ := strconv.Atoi(val)if intValue > int64(max) {return fmt.Errorf("%s 不能大于 %d", field.Name, max)}}}}}}return nil
}func main() {// 创建用户实例user := User{Name: "Alice",Age: 25,Email: "alice@example.com",Password: "abcdef",}// 验证用户信息if err := validate(user); err != nil {fmt.Println("验证失败:", err)return}// JSON序列化data, err := json.Marshal(user)if err != nil {fmt.Println("JSON序列化失败:", err)return}fmt.Println("JSON序列化结果:", string(data))// 读取自定义业务标签t := reflect.TypeOf(user)for i := 0; i < t.NumField(); i++ {field := t.Field(i)bizTag := field.Tag.Get("biz")fmt.Printf("%s 的业务标签是: %s\n", field.Name, bizTag)}
}
运行结果如下:
JSON序列化结果: {"user_name":"Alice","user_age":25,"user_email":"alice@example.com"}
Name 的业务标签是: name
Age 的业务标签是: age
Email 的业务标签是: email
Password 的业务标签是: password
代码解释
- 结构体定义:
User结构体中的每个字段都有多个标签。json标签用于指定JSON序列化时的键名以及是否忽略空值;validate标签用于定义字段的验证规则;biz标签是自定义的业务标签。 - 验证函数:
validate函数借助反射读取结构体字段的validate标签,依据规则对字段值进行验证,若不满足规则则返回错误。 - JSON序列化:在
main函数里,先创建User实例,调用validate函数验证用户信息,验证通过后使用json.Marshal对用户信息进行JSON序列化并输出结果。 - 自定义业务标签读取:通过反射读取
biz标签,输出每个字段的业务标签信息。
json标签:
json:“user_name,omitempty”:意味着在进行 JSON 序列化时,Name字段会以user_name作为键名;omitempty选项表示当Name字段为空字符串时,该字段不会出现在序列化后的 JSON 数据中。
json:“-”:表示Password字段在 JSON 序列化时会被忽略。
validate标签:
validate:“min=3,max=20”:针对Name字段定义了验证规则,要求其长度在 3 到 20 个字符之间。
validate:“min=18,max=100”:为Age字段设定了验证规则,要求其值在 18 到 100 之间。
validate:“email”:要求Email字段的值必须是一个有效的邮箱地址。
validate:“min=6”:规定Password字段的长度至少为 6 个字符。
biz标签:这是自定义的业务标签,为每个字段添加了业务相关的标识,像biz:“name” 、biz:"age"等,方便在业务逻辑里进行区分和处理。
通过这个示例,你能看到结构体标签在不同场景下的强大作用,可在实际开发中依据需求灵活运用。
相关文章:
GO语言入门-反射5(结构体的Tag)
12.5 结构体的 Tag 在定义结构体类型时,可以在字段后面加上一个字符串,称为 Struct Tag。Tag 主要用来补充附加信息。 Tag 由多个 key - value 构成,并以空格来分隔,key 和 value 之间用英文的冒号分隔。其格式如下:…...
免费下载 | 2025电力数据资产管理体系白皮书
本文是一份关于2025年电力数据资产管理体系的白皮书,详细阐述了电力数据要素和数据资产管理的现状、挑战、发展进程以及电网数据资产管理体系的构建与实践。白皮书强调了数据作为生产要素的重要性,并提出了电网数据资产管理体系的创新模式,旨…...
4185 费马小定理求逆元
4185 费马小定理求逆元 ⭐️难度:简单 🌟考点:费马小定理 📖 📚 import java.util.Scanner; import java.util.Arrays;public class Main {static int[][] a;public static void main(String[] args) {Scanner sc …...
处理Excel表不等长时间序列用tsfresh提取时序特征
我原本的时间序列格式是excel表记录的,每一行是一条时间序列,时间序列不等长。 要把excel表数据读取出来之后转换成extract_features需要的格式。 1.读取excel表数据 import pandas as pd import numpy as np from tsfresh import extract_features mda…...
从keys到SCAN:Redis批量删除的进化之路
标签:Redis、批量删除、前缀匹配、性能优化 一、痛点分析:为什么需要批量删除指定前缀的键? 在 Redis 使用过程中,我们经常会遇到这样的场景: 需要对某一类数据进行清理,例如用户会话、缓存数据等,而这些数据通常以某种前缀命名(如 user:session:*、cache:data:*)。如…...
界面控件DevExpress WinForms v25.1新功能预览 - 聚焦用户体验升级
DevExpress WinForms拥有180组件和UI库,能为Windows Forms平台创建具有影响力的业务解决方案。DevExpress WinForms能完美构建流畅、美观且易于使用的应用程序,无论是Office风格的界面,还是分析处理大批量的业务数据,它都能轻松胜…...
卷积神经网络(CNN)基础
目录 一、应用场景 二、卷积神经网络的结构 1. 输入层(Input Layer) 2. 卷积层(Convolutional Layer) 3. 池化层(Pooling Layer) 最大池化(max_pooling)或平均池化(…...
Android Spotify-v9.0.36.443-arm64-Experimental Merged版
Android Spotify 链接:https://pan.xunlei.com/s/VONXTdIv9d4FnAiNMMliIAEJA1?pwdxt7q# Android Spotify-v9.0.36.443-arm64-Experimental Merged版 享受高达256kbps的AAC音频。...
html元素转图像之深入探索 html - to - image:功能、应用与实践
html元素转图像之深入探索 html-to-image:功能、应用与实践 一、引言 使用该插件 需要注意页面上的图片都能正常显示,否则会报错,或生成的图片有误,注意注意。 在当今数字化内容丰富多样的时代,将网页上的特定 HTML…...
LLM之Agent(十六)| MCP已“过时”?Google近期推出Agent2Agent 协议 (A2A)
如今,企业越来越多地构建和部署自主代理,以帮助扩展、自动化和增强整个工作场所的流程 - 从订购新笔记本电脑到协助客户服务代表,再到协助供应链规划。 为了最大限度地发挥代理 AI 的优势,这些代理能够在一个动态的、多代理的生态…...
Transformer 训练:AutoModelForCausalLM,AutoModelForSequenceClassification
Transformer 训练:AutoModelForCausalLM,AutoModelForSequenceClassification 目录 Transformer 训练:AutoModelForCausalLM,AutoModelForSequenceClassification`AutoTokenizer.from_pretrained(model_name, trust_remote_code=True)`功能概述参数解释`AutoModelForSequen…...
网络安全1
一、网络安全的定义与重要性 定义 网络安全(信息技术安全):保护计算机系统和网络免受电子攻击的技术和过程,包括保护个人信息和企业数据不被盗窃、破坏或非法访问。涵盖范围:网络设备、数据传输、系统运行安全。 重要…...
Java学习总结-端口-协议
端口号:一个16位的二进制,范围是0-65535 端口分类: 周知端口:0-1023,被预先定义的知名应用占用(如:HTTP占用80,FTP占用21) 注册端口:1024-49151࿰…...
克魔助手(Kemob)安装与注册完整教程 - Windows/macOS双平台指南
iOS设备管理工具克魔助手便携版使用全指南 前言:为什么需要专业的iOS管理工具 在iOS开发和设备管理过程中,开发者经常需要突破系统限制,实现更深层次的控制和调试。本文将详细介绍一款实用的便携式工具的使用方法,帮助开发者快速…...
✅ Ultralytics YOLO 训练(Train)时实时获取 COCO 指标(AP):2025最新配置与代码详解 (小白友好 + B站视频)
✅ YOLO获取COCO指标(4): 训练(Train)启用COCO API评估(实时监控AP指标)| 发论文必看! | Ultralytics | 小白友好 文章目录 一、问题定位二、原理分析三、解决方案与实践案例步骤 1: 在 model.train() 调用中设置 save_jsonTrue步骤 2: 修改 …...
qwen-vl 实现OCR的测试
OCR 技术是数字化时代必不可少的实用工具。以前都依赖专业的公司的专业软件才能完成。成本很高。也正因为如此,我国纸质资料的数字化并不普及。基于大模型的ORC 也许会改变这样的现状。 文本识别,也称为光学字符识别 (OCR),可以将印刷文本或…...
算法训练之动态规划(五)——简单多状态问题
♥♥♥~~~~~~欢迎光临知星小度博客空间~~~~~~♥♥♥ ♥♥♥零星地变得优秀~也能拼凑出星河~♥♥♥ ♥♥♥我们一起努力成为更好的自己~♥♥♥ ♥♥♥如果这一篇博客对你有帮助~别忘了点赞分享哦~♥♥♥ ♥♥♥如果有什么问题可以评论区留言或者私信我哦~♥♥♥ ✨✨✨✨✨✨ 个…...
C++ 大数相加(简要版)
#include <algorithm> #include <iterator> class Solution { public:/*** 计算两个数之和* param s string字符串 表示第一个整数* param t string字符串 表示第二个整数* return string字符串*/string solve(string s, string t) {// 处理空字符串的情况…...
SVMSPro分布式综合安防管理平台-->以S3存储革新,开启智能安防新纪元
SVMSPro分布式综合安防管理平台–>以S3存储革新,开启智能安防新纪元 在数字化转型浪潮下,企业安防管理正面临海量数据存储、跨区域协同以及数据安全的严峻挑战。如何实现高效、弹性、低成本的存储扩容?如何确保关键录像数据万无一失&…...
KV Cache大模型推理加速功能
KV Cache KV Cache是大模型标配的推理加速功能,也是推理过程中,显存资源巨大开销的元凶之一。在模型推理时,KV Cache在显存占用量可达30%以上。 目前大部分针对KV Cache的优化工作,主要集中在工程上。比如著名的VLLM,…...
速盾:高防CDN节点对收录有影响吗?
引言 搜索引擎收录是网站运营中至关重要的环节,它直接影响着网站的曝光度和流量。近年来,随着网络安全威胁的增加,许多企业开始采用高防CDN(内容分发网络)来保护其网站免受DDoS攻击和其他形式的网络攻击。然而&#x…...
脑科学与人工智能的交叉:未来智能科技的前沿与机遇
引言 随着科技的迅猛发展,脑科学与人工智能(AI)这两个看似独立的领域正在发生深刻的交汇。脑机接口、神经网络模型、智能机器人等前沿技术,正带来一场跨学科的革命。这种结合不仅推动了科技进步,也在医疗、教育、娱乐等…...
Linux 系统中从源码编译安装软件
以下是 Linux 系统中 从源码编译安装软件 的详细步骤和注意事项,帮助你掌握这一高级操作技能: 一、编译安装的核心流程 1. 下载源码包(通常为 .tar.gz/.tar.bz2/.tar.xz) 2. 解压源码包 3. 进入源码目录 4. 配置编译参数…...
docker 运行自定义化的服务-后端
docker 运行自定义化的服务-前端-CSDN博客 运行自定义化的后端服务 具体如下: ①打包后端项目,形成jar包 ②编写dockerfile文件,文件内容如下: # 使用官方 OpenJDK 镜像 FROM jdk8:1.8LABEL maintainer"ATB" version&…...
基于关键字定位的自动化PDF合同拆分
需求背景: 问题描述: 我有一份包含多份合同的PDF文件,需要将这些合同分开并进行解析。 传统方法(如以固定页数作为分割点)不够灵活,无法满足需求。 现有方法的不足: 网上找到的工具大多依赖手动…...
spring security 使用auth2.0
在 Spring Security 中集成 OAuth 2.0 可以实现安全的第三方认证和资源保护。以下是完整的配置指南和代码示例: 一、OAuth 2.0 核心概念 角色作用资源所有者用户(授权访问资源的人)客户端应用(如Web、移动端)授权服务…...
NO.82十六届蓝桥杯备战|动态规划-从记忆化搜索到动态规划|下楼梯|数字三角形(C++)
记忆化搜索 在搜索的过程中,如果搜索树中有很多重复的结点,此时可以通过⼀个"备忘录",记录第⼀次搜索到的结果。当下⼀次搜索到这个结点时,直接在"备忘录"⾥⾯找结果。其中,搜索树中的⼀个⼀个结点…...
ubuntu 服务器版本常见问题
一、系统安装与初始化 1. 安装过程中断或失败 原因:镜像损坏、硬件兼容性、磁盘分区错误。 解决: 验证 ISO 文件的完整性(计算 SHA256 校验和)。 检查 BIOS/UEFI 设置(禁用 Secure Boot)。 使用手动分区模式,确保根分区(/)和 EFI 分区(如有)正确配置。 2. 系…...
【时时三省】(C语言基础)用switch语句实现多分支选择结构 例题
山不在高,有仙则名。水不在深,有龙则灵。 ----CSDN 时时三省 例题: 用switch语句处理菜单命令。在许多应用程序中,用菜单对流程进行控制,例如从键盘输入一个 A 或 a 字符,就会执行A操作,输入一…...
全域数字化:从“智慧城市”到“数字生命体”的进化之路
一、国家战略下的城市数字化浪潮 2024年5月,国家四部委联合发布《关于深化智慧城市发展 推进城市全域数字化转型的指导意见》,明确提出以数据为引擎,系统性重塑城市技术架构与管理流程,推动城市治理迈向“全域协同、数实融合”的…...
