Just a few weeks until the 2021 JavaScript Full-Stack Bootcamp opens.
Signup to the waiting list!
Tags are a way to attach additional information to a struct field.
The Go spec in the Struct types definition defines tags as
A field declaration may be followed by an optional string literal tag, which becomes an attribute for all the fields in the corresponding field declaration. An empty tag string is equivalent to an absent tag. The tags are made visible through a reflection interface and take part in type identity for structs but are otherwise ignored.
and provides an example:
struct {
x, y float64 "" // an empty tag string is like an absent tag
name string "any string is permitted as a tag"
_ [4]byte "ceci n'est pas un champ de structure"
}
// A struct corresponding to a TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers;
// they follow the convention outlined by the reflect package.
struct {
microsec uint64 `protobuf:"1"`
serverIP6 uint64 `protobuf:"2"`
}
A real-world example
A common use-case for this is when unmarshaling JSON, as I explain in JSON processing with Go.
In that post, the example
type Member struct {
Age int `json:"age,string"`
}
tells json.Unmarshal()
to put the age
JSON property, a string
, and put it in the Age
field of Member
, translating to an int
. In this example, we pass json
two informations, separated with a comma.
Format of tags
Tags use the key:"value"
format. It’s not a strict rule, but a convention, which provides built-in parsing. In that example,we have only one key-value pair, but we could have more than one:
type Member struct {
Age int `json:"age,string" xml:"the_age,string"`
}
The key by convention is the name of the package we want to target. In the above example, encoding/json
and encoding/xml
.
But tags can be used also by ourselves in our own libraries, they are not just reserved for the standard library.
What are tags used for?
Different packages use tags for different reasons.
You’ll see them used in encoding libs, like json, xml, bson, yaml, but also in ORM / database libs, and even filling a struct with form data.
The following list was posted on SO and is quite comprehensive:
json
- used by theencoding/json
package, detailed atjson.Marshal()
xml
- used by theencoding/xml
package, detailed atxml.Marshal()
bson
- used by gobson, detailed atbson.Marshal()
protobuf
- used bygithub.com/golang/protobuf/proto
, detailed in the package docyaml
- used by thegopkg.in/yaml.v2
package, detailed atyaml.Marshal()
db
- used by thegithub.com/jmoiron/sqlx
packageorm
- used by thegithub.com/astaxie/beego/orm
package, detailed at Models – Beego ORMgorm
- used by thegithub.com/jinzhu/gorm
package, examples can be found in their doc: Modelsdatastore
- used byappengine/datastore
(Google App Engine platform, Datastore service), detailed at Propertiesschema
- used bygithub.com/gorilla/schema
to fill astruct
with HTML form values, detailed in the package docasn
- used by theencoding/asn1
package, detailed atasn1.Marshal()
andasn1.Unmarshal()
There are many other usages in the wild. For example mcuadros/go-defaults use s it to set default values for struct fields, and asaskevich/govalidator allows to add tags that determine validation (that’s just one possible way of validating, alternatives exist).
fatih/gomodifytags allows to edit tags at runtime,
Using tags in your code
To use tags in your own code, you can use the reflect
package.
Let’s try getting age
in a Member struct. The following code
package main
import (
"fmt"
"reflect"
)
type Member struct {
Age int `something:"age"`
}
func main() {
member := Member{34}
t := reflect.TypeOf(member)
field := t.Field(0)
//field, _ := t.FieldByName("Age") //alternative
fmt.Print(field.Tag.Get("something"))
}
will print age
, thanks to adhering to the key:"value"
format for our tag.
The 2021 JavaScript Full-Stack Bootcamp will start at the end of March 2021. Don't miss this opportunity, signup to the waiting list!
More go tutorials:
- Using NGINX Reverse Proxy to serve Go services
- Making a copy of a struct in Go
- The basics of a Go Web Server
- Sorting a map type in Go
- Go pointers in a nutshell
- Go Tags explained
- Go Date and Time Formatting
- JSON processing with Go
- Go Variadic Functions
- Go Strings Cheat Sheet
- The Go Empty Interface Explained
- Debugging Go with VS Code and Delve
- Named Go returns parameters
- Generating random numbers and strings in Go
- Filesystem Structure of a Go project
- Binary Search Algorithm Implemented in Go
- Using Command Line Flags in Go
- GOPATH Explained
- Build a Command Line app with Go: lolcat
- Building a CLI command with Go: cowsay
- Using Shell Pipes with Go
- Go CLI tutorial: fortune clone
- List the files in a folder with Go
- Use Go to get a list of repositories from GitHub
- Go, append a slice of strings to a file
- Go, convert a string to a bytes slice
- Visualize your local Git contributions with Go
- Getting started with Go CPU and memory profiling
- Solving the "does not support indexing" error in a Go program
- Measuring execution time in a Go program
- Building a Web Crawler with Go to detect duplicate titles
- Go Best Practices: Pointer or value receivers?
- Go Best Practices: Should you use a method or a function?
- Go Data Structures: Set
- Go Maps Cheat Sheet
- Generate implementations for generic types in Go
- Go Data Structures: Dictionary
- Go Data Structures: Hash Table
- Implement Events Listeners in Go through Channels
- Go Data Structures: Stack
- Go Data Structures: Queue
- Go Data Structures: Binary Search Tree
- Go Data Structures: Graph
- Go Data Structures: Linked List
- The complete guide to Go Data Structures
- Comparing Go Values
- Is Go object oriented?
- Working with a SQL Database in Go
- Using environment variables in Go
- Go tutorial: REST API backed by PostgreSQL
- Enabling CORS on a Go Web Server
- Deploying a Go Application in a Docker Container
- Why Go is a powerful language to learn as a PHP developer
- Go, remove the io.Reader.ReadString newline char
- Go, how to watch changes and rebuild your program
- Go, count the months since a date
- Accessing HTTP POST parameters in Go