自拍偷在线精品自拍偷,亚洲欧美中文日韩v在线观看不卡

為什么 Go 語言 struct 要使用 Tags

開發(fā) 前端
在本文中,我們將探討為什么 Go 語言中需要使用 struct tags,以及 struct tags 的使用場景和優(yōu)勢。

在 Go 語言中,struct 是一種常見的數(shù)據(jù)類型,它可以用來表示復(fù)雜的數(shù)據(jù)結(jié)構(gòu)。在 struct 中,我們可以定義多個字段,每個字段可以有不同的類型和名稱。

除了這些基本信息之外,Go 還提供了 struct tags,它可以用來指定 struct 中每個字段的元信息。

在本文中,我們將探討為什么 Go 語言中需要使用 struct tags,以及 struct tags 的使用場景和優(yōu)勢。

struct tags 的使用

struct tags 使用還是很廣泛的,特別是在 json 序列化,或者是數(shù)據(jù)庫 ORM 映射方面。

圖片

在定義上,它以 key:value 的形式出現(xiàn),跟在 struct 字段后面,除此之外,還有以下幾點(diǎn)需要注意:

使用反引號

在聲明 struct tag 時,使用反引號 ` 包圍 tag 的值,可以防止轉(zhuǎn)義字符的影響,使 tag 更容易讀取和理解。例如:

type User struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
}

避免使用空格

在 struct tag 中,應(yīng)該避免使用空格,特別是在 tag 名稱和 tag 值之間。使用空格可能會導(dǎo)致編碼或解碼錯誤,并使代碼更難以維護(hù)。例如:

// 不規(guī)范的寫法
type User struct {
ID int `json: "id" db: "id"`
Name string `json: "name" db: "name"`
Email string `json: "email" db: "email"`
}

// 規(guī)范的寫法
type User struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
}

避免重復(fù)

在 struct 中,應(yīng)該避免重復(fù)使用同一個 tag 名稱。如果重復(fù)使用同一個 tag 名稱,編譯器可能會無法識別 tag,從而導(dǎo)致編碼或解碼錯誤。例如:

// 不規(guī)范的寫法
type User struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"name"`
}

// 規(guī)范的寫法
type User struct {
ID int `json:"id" db:"id"`
Name string `json:"name" db:"name"`
Email string `json:"email" db:"email"`
}

使用標(biāo)準(zhǔn)化的 tag 名稱

為了使 struct tag 更加標(biāo)準(zhǔn)化和易于維護(hù),應(yīng)該使用一些標(biāo)準(zhǔn)化的 tag 名稱。

例如,對于序列化和反序列化,可以使用 json、xml、yaml? 等;對于數(shù)據(jù)庫操作,可以使用 db。

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 值分隔開。例如:

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 的反射庫提供了一些方法,可以讓我們在程序運(yùn)行時獲取和解析結(jié)構(gòu)體標(biāo)簽。

介紹這些方法之前,先來看看 reflect.StructField ,它是描述結(jié)構(gòu)體字段的數(shù)據(jù)類型。定義如下:

type StructField struct {
Name string // 字段名
Type Type // 字段類型
Tag StructTag // 字段標(biāo)簽
}

結(jié)構(gòu)體中還有一些其他字段,被我省略了,只保留了和本文相關(guān)的。

在結(jié)構(gòu)體的反射中,我們經(jīng)常使用 reflect.TypeOf? 獲取類型信息,然后使用 Type.Field? 或 Type.FieldByName()?  獲取結(jié)構(gòu)體字段的 reflect.StructField?,然后根據(jù) StructField 中的信息做進(jìn)一步處理。

例如,可以通過 StructField.Tag.Get 方法獲取結(jié)構(gòu)體字段的標(biāo)簽值。

下面看一段代碼:

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)
}

運(yùn)行以上代碼,輸出結(jié)果如下:

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

struct tags 的優(yōu)勢

使用 struct tag 的主要優(yōu)勢之一是可以在運(yùn)行時通過反射來訪問和操作 struct 中的字段。

比如在 Go Web 開發(fā)中,常常需要將 HTTP 請求中的參數(shù)綁定到一個 struct 中。這時,我們可以使用 struct tag 指定每個字段對應(yīng)的參數(shù)名稱、驗(yàn)證規(guī)則等信息。在接收到 HTTP 請求時,就可以使用反射機(jī)制讀取這些信息,并根據(jù)信息來驗(yàn)證參數(shù)是否合法。

另外,在將 struct 序列化為 JSON 或者其他格式時,我們也可以使用 struct tag 來指定每個字段在序列化時的名稱和規(guī)則。

此外,使用 struct tag 還可以提高代碼的可讀性和可維護(hù)性。在一個大型的項(xiàng)目中,struct 中的字段通常會包含很多不同的元信息,比如數(shù)據(jù)庫中的表名、字段名、索引、驗(yàn)證規(guī)則等等。

如果沒有 struct tag,我們可能需要將這些元信息放在注釋中或者在代碼中進(jìn)行硬編碼。這樣會讓代碼變得難以維護(hù)和修改。而使用 struct tag 可以將這些元信息與 struct 字段緊密關(guān)聯(lián)起來,使代碼更加清晰和易于維護(hù)。

常用的 struct tags

在 Go 的官方 wiki 中,有一個常用的 struct tags 的庫的列表,我復(fù)制在下面了,感興趣的同學(xué)可以看看源碼,再繼續(xù)深入學(xué)習(xí)。

Tag

Documentation

xml

??https://pkg.go.dev/encoding/xml??

json

??https://pkg.go.dev/encoding/json??

asn1

??https://pkg.go.dev/encoding/asn1??

reform

??https://pkg.go.dev/gopkg.in/reform.v1??

dynamodb

??https://docs.aws.amazon.com/sdk-for-go/api/service/dynamodb/dynamodbattribute/#Marshal??

bigquery

??https://pkg.go.dev/cloud.google.com/go/bigquery??

datastore

??https://pkg.go.dev/cloud.google.com/go/datastore??

spanner

??https://pkg.go.dev/cloud.google.com/go/spanner??

bson

https://pkg.go.dev/labix.org/v2/mgo/bson, https://pkg.go.dev/go.mongodb.org/mongo-driver/bson/bsoncodec

gorm

??https://pkg.go.dev/github.com/jinzhu/gorm??

yaml

??https://pkg.go.dev/gopkg.in/yaml.v2??

toml

??https://pkg.go.dev/github.com/pelletier/go-toml??

validate

??https://github.com/go-playground/validator??

mapstructure

??https://pkg.go.dev/github.com/mitchellh/mapstructure??

parser

??https://pkg.go.dev/github.com/alecthomas/participle??

protobuf

??https://github.com/golang/protobuf??

db

??https://github.com/jmoiron/sqlx??

url

??https://github.com/google/go-querystring??

feature

??https://github.com/nikolaydubina/go-featureprocessing??

以上就是本文的全部內(nèi)容,如果覺得還不錯的話歡迎點(diǎn)贊,轉(zhuǎn)發(fā)和關(guān)注,感謝支持。

參考文章:

  • https://github.com/golang/go/wiki/Well-known-struct-tags
責(zé)任編輯:武曉燕 來源: AlwaysBeta
相關(guān)推薦

2012-08-13 09:15:54

Go開發(fā)語言編程語言

2011-03-08 12:59:38

proftpd

2014-11-21 10:50:26

JavaString

2017-07-03 13:33:42

AndroidItemDecorat

2024-01-02 10:38:22

Go語言數(shù)組

2011-04-14 09:30:15

集合框架

2010-05-11 10:29:06

Unix awk

2014-05-19 15:52:57

Apache StraApache

2020-04-07 16:12:56

Go編程語言開發(fā)

2014-04-25 10:05:42

OpenStack私有云公共云

2024-01-24 11:24:03

C++編程異常處理

2013-09-27 11:33:57

交換機(jī)技術(shù)Vlan技術(shù)

2015-07-02 09:40:57

R語言優(yōu)勢缺點(diǎn)

2023-09-21 09:00:00

Merge Que開發(fā)工具Mergify

2014-01-03 10:59:34

2023-12-27 08:12:04

切片Go語言

2021-12-24 17:01:29

Linux工具系統(tǒng)

2024-01-01 08:57:55

ODBCSqlServer數(shù)據(jù)庫

2012-08-20 09:16:15

Go語言

2022-04-26 16:56:20

行為數(shù)據(jù)數(shù)據(jù)
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號