结构体标签 #
一、标签概述 #
结构体标签是为字段添加的元数据,通过反射读取。
二、标签语法 #
2.1 基本语法 #
go
type User struct {
Name string `tag1:"value1" tag2:"value2"`
}
2.2 多标签 #
go
type User struct {
Name string `json:"name" xml:"name" db:"user_name"`
}
2.3 标签格式 #
- 键值对形式:
key:"value" - 多个标签用空格分隔
- 值可以用逗号分隔多个选项
三、JSON标签 #
3.1 基本用法 #
go
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email"`
}
user := User{Name: "Alice", Age: 25, Email: "alice@example.com"}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice","age":25,"email":"alice@example.com"}
3.2 忽略字段 #
go
type User struct {
Name string `json:"name"`
Password string `json:"-"` // 序列化时忽略
}
3.3 omitempty #
字段为零值时忽略:
go
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"`
}
user := User{Name: "Alice"}
data, _ := json.Marshal(user)
fmt.Println(string(data))
// {"name":"Alice"}
3.4 字符串选项 #
将数值转为字符串:
go
type Data struct {
Number int `json:"number,string"`
}
data := Data{Number: 42}
result, _ := json.Marshal(data)
fmt.Println(string(result))
// {"number":"42"}
四、XML标签 #
4.1 基本用法 #
go
type Person struct {
XMLName xml.Name `xml:"person"`
Name string `xml:"name"`
Age int `xml:"age"`
}
p := Person{Name: "Alice", Age: 25}
data, _ := xml.Marshal(p)
fmt.Println(string(data))
// <person><name>Alice</name><age>25</age></person>
4.2 属性 #
go
type Person struct {
XMLName xml.Name `xml:"person"`
ID int `xml:"id,attr"`
Name string `xml:"name"`
}
4.3 嵌套元素 #
go
type Address struct {
City string `xml:"city"`
}
type Person struct {
Name string `xml:"name"`
Address Address `xml:"address"`
}
五、数据库标签 #
5.1 GORM标签 #
go
type User struct {
ID uint `gorm:"primaryKey"`
Name string `gorm:"size:100;not null"`
Email string `gorm:"uniqueIndex"`
CreatedAt time.Time `gorm:"autoCreateTime"`
}
5.2 常用GORM标签 #
| 标签 | 说明 |
|---|---|
| primaryKey | 主键 |
| uniqueIndex | 唯一索引 |
| index | 普通索引 |
| not null | 非空 |
| size | 字符串长度 |
| default | 默认值 |
六、验证标签 #
6.1 validator库 #
go
type User struct {
Name string `validate:"required,min=2,max=100"`
Email string `validate:"required,email"`
Age int `validate:"gte=0,lte=130"`
}
func main() {
validate := validator.New()
user := User{Name: "A", Email: "invalid", Age: 200}
err := validate.Struct(user)
if err != nil {
fmt.Println(err)
}
}
6.2 常用验证标签 #
| 标签 | 说明 |
|---|---|
| required | 必填 |
| 邮箱格式 | |
| url | URL格式 |
| min, max | 最小/最大值 |
| len | 长度 |
| oneof | 枚举值 |
七、反射获取标签 #
7.1 基本用法 #
go
type User struct {
Name string `json:"name" validate:"required"`
}
func main() {
t := reflect.TypeOf(User{})
field, _ := t.FieldByName("Name")
fmt.Println(field.Tag.Get("json")) // name
fmt.Println(field.Tag.Get("validate")) // required
}
7.2 遍历所有字段 #
go
func printTags(v interface{}) {
t := reflect.TypeOf(v)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
fmt.Printf("Field: %s, Tag: %s\n",
field.Name, field.Tag)
}
}
7.3 Lookup方法 #
go
tag := field.Tag.Lookup("json")
if ok {
fmt.Println("json tag:", tag)
}
八、自定义标签 #
8.1 定义标签 #
go
type User struct {
Name string `custom:"user_name" format:"upper"`
}
8.2 解析自定义标签 #
go
func processCustomTag(v interface{}) {
t := reflect.TypeOf(v)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
if custom := field.Tag.Get("custom"); custom != "" {
fmt.Printf("Custom name for %s: %s\n",
field.Name, custom)
}
}
}
8.3 实际应用 #
go
type FieldMapping struct {
FieldName string
ColumnName string
Required bool
}
func ParseModel(v interface{}) []FieldMapping {
t := reflect.TypeOf(v)
var mappings []FieldMapping
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
mapping := FieldMapping{
FieldName: field.Name,
ColumnName: field.Tag.Get("db"),
Required: field.Tag.Get("required") == "true",
}
mappings = append(mappings, mapping)
}
return mappings
}
九、实际应用 #
9.1 配置映射 #
go
type Config struct {
Host string `config:"host" default:"localhost"`
Port int `config:"port" default:"8080"`
Database string `config:"database" default:"mydb"`
}
func LoadConfig(cfg interface{}) error {
v := reflect.ValueOf(cfg).Elem()
t := v.Type()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
key := field.Tag.Get("config")
def := field.Tag.Get("default")
if val := os.Getenv(key); val != "" {
v.Field(i).SetString(val)
} else if def != "" {
v.Field(i).SetString(def)
}
}
return nil
}
9.2 表单绑定 #
go
type LoginForm struct {
Username string `form:"username" validate:"required"`
Password string `form:"password" validate:"required,min=6"`
}
func BindForm(r *http.Request, form interface{}) error {
v := reflect.ValueOf(form).Elem()
t := v.Type()
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
formKey := field.Tag.Get("form")
if formKey != "" {
val := r.FormValue(formKey)
v.Field(i).SetString(val)
}
}
return nil
}
十、最佳实践 #
10.1 标签命名规范 #
go
// 好
type User struct {
Name string `json:"name" db:"name"`
}
// 避免
type User struct {
Name string `json:"user_name_in_json"`
}
10.2 保持一致性 #
go
type User struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
}
10.3 文档化标签 #
go
type User struct {
Name string `json:"name" validate:"required,min=2"`
// Name is the user's display name (2-100 characters)
}
十一、总结 #
标签要点:
| 标签 | 用途 |
|---|---|
| json | JSON序列化 |
| xml | XML序列化 |
| gorm | 数据库ORM |
| validate | 数据验证 |
| form | 表单绑定 |
关键点:
- 元数据:标签为字段添加元数据
- 反射读取:通过reflect包读取标签
- 标准库支持:json、xml等标准库支持标签
- 第三方库:gorm、validator等广泛使用标签
- 自定义标签:可以定义自己的标签
准备好学习接口了吗?让我们进入下一章!
最后更新:2026-03-26