Original link: What does it mean to tag a structure in Go language?
Preface
Hello, everyone, my name is asong
. Today I want to share with you Go
language, and how to customize your own structure tag analysis.
When most beginners look at the company's project code, some structure definitions they see will look like this:
type Location struct {
Longitude float32 `json:"lon,omitempty"`
Latitude float32 `json:"lat,omitempty"`
}
There will be a label after the field. What is the use of this label?
In the above example, the label json:"lon,omitempty"
means that when the value of the structure field is encoded as the json
object, each derived field becomes a member of the object. The name of this member is lon
or lat
, and when the field is null , Do not export this field; the summary is lon
, lat
is the name of the renamed member, and omitempty
used to determine whether the member is exported.
Seeing this, some friends may be curious, how did you know how to use this? Can I write labels casually?
Next, we will reveal the secret a little bit, and drive! ! !
What is a label
Go
language provides structure tags that can be discovered through reflection. These are widely used json/xml
orm
framework also supports structure tags. The above example is used because encoding/json
supports structure tags, but He has his own labeling rules; but they all have a general rule, this rule cannot be changed, the specific format is as follows:
`key1:"value1" key2:"value2" key3:"value3"...` // 键值对用空格分隔
Structure tags can have multiple key-value pairs. Keys and values must be separated by colons, values must be enclosed in double quotation marks, and multiple key-value pairs must be separated by a space. Do not use commas! ! !
What if we want to pass multiple information in one value? The implementations in different libraries are different. In encoding/json
, multiple values are separated by commas:
`json:"lon,omitempty"`
In gorm
, multiple values are separated by semicolons:
`gorm:"column:id;primaryKey"
You need to see the documentation of the respective library to obtain the specific symbol separation.
The structure tag is associated with the member during the compilation phase, and is associated in the form of a string, which can be read out through reflection during the runtime phase.
Now that everyone knows what structure tags are, the rules are still very standardized, but it is easy to make mistakes, because the Go language does not check its format for legal key-value pairs during the compilation phase, so we accidentally wrote it wrong. It is difficult to be found, but we have the go vet
look at an example for specific use:
type User struct {
Name string `abc def ghk`
Age uint16 `123: 232`
}
func main() {
}
Then execute go vet main.go
to get the execution result:
# command-line-arguments
go_vet_tag/main.go:4:2: struct field tag `abc def ghk` not compatible with reflect.StructTag.Get: bad syntax for struct tag pair
go_vet_tag/main.go:5:2: struct field tag `123: 232` not compatible with reflect.StructTag.Get: bad syntax for struct tag value
bad syntax for struct tag pair
tells us that the key-value pair has a syntax error, and the bad syntax for struct tag value
value has a syntax error.
Therefore, it is necessary go vet
as the CI
Label usage scenarios
Go
official has helped sort out which libraries already support struct tag
: https://github.com/golang/go/wiki/Well-known-struct-tags.
Like json
, yaml
, gorm
, validate
, mapstructure
, protobuf
structure label these libraries is very common, gin
framework to integrate validate
library used for parameter validation, a lot of convenience, before writing an article about validate
The article: use the validator library for data verification. I opened ~~~ , you can pay attention to it.
For details on how these libraries are used, you can read the official documentation. They are written in detail, and they are used in specific scenarios! ! !
Custom structure label
Now we can answer the first question. The structure tag can be written at will, as long as it conforms to the grammatical rules, it can be written arbitrarily, but if some libraries do not support this tag, the tag written at will has no meaning. , If we want our tags to become meaningful, we need to provide analysis methods. The label can be obtained by reflection, so let's look at an example of how to use reflection to obtain a custom structure label.
type User struct {
Name string `asong:"Username"`
Age uint16 `asong:"age"`
Password string `asong:"min=6,max=10"`
}
func getTag(u User) {
t := reflect.TypeOf(u)
for i := 0; i < t.NumField(); i++ {
field := t.Field(i)
tag := field.Tag.Get("asong")
fmt.Println("get tag is ", tag)
}
}
func main() {
u := User{
Name: "asong",
Age: 5,
Password: "123456",
}
getTag(u)
}
The results of the operation are as follows:
get tag is Username
get tag is age
get tag is min=6,max=10
Here we use TypeOf
method, and then traverse the fields, each field StructField
has a member variable Tag
:
// A StructField describes a single field in a struct.
type StructField struct {
Name string
PkgPath string
Type Type // field type
Tag StructTag // field tag string
Offset uintptr // offset within struct, in bytes
Index []int // index sequence for Type.FieldByIndex
Anonymous bool // is an embedded field
}
Tag
is a built-in type, providing Get
, Loopup
two methods to parse the value in the tag and return the value of the specified key:
func (tag StructTag) Get(key string) string
func (tag StructTag) Lookup(key string) (value string, ok bool)
Get
also calls the Lookup
method internally. The difference is that Lookup
key
exists and is in the tag through the return value Get
method completely ignores this judgment.
Summarize
This article mainly introduces what Go
language is, and how to use reflection to obtain the structure label. In our daily development, we use some libraries to provide good labels, and we rarely develop and use them ourselves. If you are interested, you can read validae
to see how he parses tag
in the structure, or you can implement a verification library yourself as a hands-on project.
The code in the article has been uploaded github
: https://github.com/asong2020/Golang_Dream/tree/master/code_demo/struct_tag_demo
, this is the end of this article, my name is asong
, see you in the next issue.
Welcome to pay attention to the public account: Golang DreamWorks
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。