Go 语言中的 Struct Tag 的用法详解

在 Go 语言中,结构体字段标签(Struct Tag) 是一种用于给字段添加元信息(metadata)的机制,常用于序列化(如 JSON、XML)、ORM 映射、验证等场景。你在开发 Web 应用或处理数据交互时,一定会经常看到类似下面的写法:

go 复制代码
type User struct {
	Username string `json:"username"`
	Token    string `json:"token"`
}

其中的 json:"token" 就是字段标签,它并不影响 Go 语言本身的语法逻辑,但它在使用反射(reflect)时非常有用,特别是当你用标准库如 encoding/json 时。

一、结构体标签的基本语法

结构体标签是一对反引号 ` 包起来的字符串,里面是一个键值对的形式:

go 复制代码
FieldName FieldType `key:"value"`
//可以写多个键值对:
FieldName FieldType `json:"token" xml:"token" validate:"required"`

这些标签是给其他包(通常是库)解析使用的,不影响 Go 编译器的行为。

二、json:"token"的具体含义

当你用 encoding/json 包将结构体编码为 JSON 时,这个标签的作用是:

指定序列化后的字段名

默认情况下,Go 会使用结构体字段名作为 JSON 的字段名。但注意:
Go 结构体的字段是大写开头(导出);
JSON 通常用小写字段名(如 "token");

为了统一后端返回格式并满足前端规范,我们可以显式指定字段名:

go 复制代码
type User struct {
	Token string `json:"token"`
}

生成的json:

go 复制代码
{
  "token": "abc123"
}

反序列化时也生效

当你将 JSON 反序列化成结构体时,Go 会根据标签来找对应字段。例如上面的json格式能成功映射到:

go 复制代码
var user User
json.Unmarshal(data, &user)
// user.Token == "abc123"

三、常见的标签格式变体

go 复制代码
type User struct {
	Token string `json:"token"`           // 显式指定字段名为 token
	Age   int    `json:"-"`               // 忽略该字段,不进行序列化
	Email string `json:"email,omitempty"` // 若为空则忽略该字段
}

json:"-": 表示这个字段永远不会被编码或解码,即不导出。

json:"email,omitempty": 表示只有字段不为默认值时,才会被编码到 JSON(比如字符串为 "",数字为 0 就会忽略)。

四、使用示例

go 复制代码
package main

import (
	"encoding/json"
	"fmt"
)

type User struct {
	Username string `json:"username"`
	Token    string `json:"token"`
	Age      int    `json:"-"` // 不导出
}

func main() {
	user := User{
		Username: "Alice",
		Token:    "abc123",
		Age:      30,
	}

	data, _ := json.Marshal(user)
	fmt.Println(string(data))
}
//{"username":"Alice","token":"abc123"}

五、使用建议

  1. 字段必须导出(首字母大写),否则即使有 tag,json 包也不会访问它。
  2. 推荐统一使用小写 JSON 字段名:json:"username",更符合前端 JSON 风格。
  3. 如有嵌套结构体,注意为子结构体也添加 json 标签。!!! ~~~~~~~~!!! 务必都为添加 json 标签的结构体!!!!不然前端解析不了!!!

疑问? 如果json tag为"-" ,为什么不把结构体首字母小写呢 不是一个效果吗?

json:"-"的用途

json:"-" 是明确告诉 encoding/json:"这个字段你不要处理,序列化/反序列化时忽略它"。这在结构体对外暴露字段但不希望被 JSON 处理时非常有用,比如:

go 复制代码
type User struct {
	Username string `json:"username"`
	Password string `json:"-"` // 不想被输出!
}

你仍然可以在后端处理 Password 字段,但它不会出现在 JSON 输出中。这是安全和结构清晰性方面的明确表达。

总结:选择建议

目的 用法推荐
字段仅用于内部逻辑,不想暴露出去 小写字段
字段对程序可见,但不想在 JSON 中出现 json:"-"
需要 JSON 中出现但字段名不同 json:"your_name"
希望字段在为空时不出现 json:"your_name,omitempty"

简单例子:

go 复制代码
type RespMsg struct {
	Code int         `json:"code"`
	Msg  string      `json:"msg"`
	Data interface{} `json:"data"`
}

type LoginData struct {
	Token    string `json:"token"`
	Username string `json:"username"`
	Location string `json:"location"`
}

rsp := RespMsg{
	Code: 200,
	Msg:  "success",
	Data: LoginData{
		Token:    userToken,
		Username: username,
		Location: "/static/view/home.html",
	},
}

这样返回的 JSON 就是:

json 复制代码
{
  "code": 200,
  "msg": "success",
  "data": {
    "token": "...",
    "username": "...",
    "location": "..."
  }
}

前端用 resp.data.token、resp.data.username 就不会有大小写错位的问题。

相关推荐
emplace_back23 分钟前
C# 项目
开发语言·c#
(・Д・)ノ29 分钟前
python打卡day33
开发语言·python
小革36042 分钟前
JAVA批量发送邮件(含excel内容)
开发语言·python·excel
阿梦Anmory42 分钟前
[解决conda创建新的虚拟环境没用python的问题]
开发语言·python·conda
心扬1 小时前
python容器
开发语言·python
有梦想的攻城狮2 小时前
spring中的BeanFactoryAware接口详解
java·后端·spring·beanfactory
我漫长的孤独流浪2 小时前
STL中的Vector(顺序表)
开发语言·c++·算法
liubo666_2 小时前
JVM梳理(逻辑清晰)
java·jvm·后端
一刀到底2112 小时前
java 在用redis 的时候,如何合理的处理分页问题? redis应当如何存储性能最佳
java·开发语言·redis
软考真题app2 小时前
软件设计师考试三大核心算法考点深度解析(红黑树 / 拓扑排序 / KMP 算法)真题考点分析——求三连
java·开发语言·算法·软考·软件设计师