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:

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

play

will print “something”, thanks to adhering to the key:"value" format for our tag.

Want to hire me?

I'm currently considering remote job opportunities.

I'm interested in Go and/or JavaScript senior software engineer positions.

Read more about me and if you're interested, get in touch.