By liamzebedee


2012-06-02 00:10:27 8 Comments

In the Go Language Specification, it mentions a brief overview of tags:

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. The tags are made visible through a reflection interface but are otherwise ignored.

// A struct corresponding to the TimeStamp protocol buffer.
// The tag strings define the protocol buffer field numbers.
struct {
  microsec  uint64 "field 1"
  serverIP6 uint64 "field 2"
  process   string "field 3"
}

This is a very short explanation IMO, and I was wondering if anyone could provide me with what use these tags would be?

2 comments

@icza 2015-06-17 10:49:23

A tag for a field allows you to attach meta-information to the field which can be acquired using reflection. Usually it is used to provide transformation info on how a struct field is encoded to or decoded from another format (or stored/retrieved from a database), but you can use it to store whatever meta-info you want to, either intended for another package or for your own use.

As mentioned in the documentation of reflect.StructTag, by convention the value of a tag string is a space-separated list of key:"value" pairs, for example:

type User struct {
    Name string `json:"name" xml:"name"`
}

The key usually denotes the package that the subsequent "value" is for, for example json keys are processed/used by the encoding/json package.

If multiple information is to be passed in the "value", usually it is specified by separating it with a comma (','), e.g.

Name string `json:"name,omitempty" xml:"name"`

Usually a dash value ('-') for the "value" means to exclude the field from the process (e.g. in case of json it means not to marshal or unmarshal that field).

Example of accessing your custom tags using reflection

We can use reflection (reflect package) to access the tag values of struct fields. Basically we need to acquire the Type of our struct, and then we can query fields e.g. with Type.Field(i int) or Type.FieldByName(name string). These methods return a value of StructField which describes / represents a struct field; and StructField.Tag is a value of type StructTag which describes / represents a tag value.

Previously we talked about "convention". This convention means that if you follow it, you may use the StructTag.Get(key string) method which parses the value of a tag and returns you the "value" of the key you specify. The convention is implemented / built into this Get() method. If you don't follow the convention, Get() will not be able to parse key:"value" pairs and find what you're looking for. That's also not a problem, but then you need to implement your own parsing logic.

Also there is StructTag.Lookup() (was added in Go 1.7) which is "like Get() but distinguishes the tag not containing the given key from the tag associating an empty string with the given key".

So let's see a simple example:

type User struct {
    Name  string `mytag:"MyName"`
    Email string `mytag:"MyEmail"`
}

u := User{"Bob", "[email protected]"}
t := reflect.TypeOf(u)

for _, fieldName := range []string{"Name", "Email"} {
    field, found := t.FieldByName(fieldName)
    if !found {
        continue
    }
    fmt.Printf("\nField: User.%s\n", fieldName)
    fmt.Printf("\tWhole tag value : %q\n", field.Tag)
    fmt.Printf("\tValue of 'mytag': %q\n", field.Tag.Get("mytag"))
}

Output (try it on the Go Playground):

Field: User.Name
    Whole tag value : "mytag:\"MyName\""
    Value of 'mytag': "MyName"

Field: User.Email
    Whole tag value : "mytag:\"MyEmail\""
    Value of 'mytag': "MyEmail"

GopherCon 2015 had a presentation about struct tags called:

The Many Faces of Struct Tags (slide) (and a video)

Here is a list of commonly used tag keys:

@Darth Egregious 2015-07-01 13:53:41

Excellent answer. Way more useful info in here than in the one with ten times this karma.

@Steven Ferrer 2017-10-09 02:39:35

very nice summary!

@Alberto Megía 2017-11-15 19:56:04

What an awesome answer

@JumpAlways 2017-11-18 22:13:57

Great answer! Thank you!

@Himanshu 2017-12-29 14:00:55

Well done ! Appreciated

@Sam Holmes 2018-02-20 09:09:05

Amazing answer, thank you for all of this information!

@muthukumar 2018-02-22 13:24:37

Great Answer I am using this for mongoose Colections Very help ful

@M. Gopal 2018-07-25 12:54:20

Nicely summarized answer...

@CommonSenseCode 2018-07-31 14:42:11

Wow I learned so much from this answer thanks!

@Himanshu 2018-10-23 07:37:09

@icza, Hi I have a question stackoverflow.com/questions/52943450/…. Please can you help me with this understanding of go routine, whenever you get time. Thanks.

@jdi 2012-06-02 00:24:34

Here is a really simple example of tags being used with the encoding/json package to control how fields are interpreted during encoding and decoding:

Try live: http://play.golang.org/p/BMeR8p1cKf

package main

import (
    "fmt"
    "encoding/json"
)

type Person struct {
    FirstName  string `json:"first_name"`
    LastName   string `json:"last_name"`
    MiddleName string `json:"middle_name,omitempty"`
}

func main() {
    json_string := `
    {
        "first_name": "John",
        "last_name": "Smith"
    }`

    person := new(Person)
    json.Unmarshal([]byte(json_string), person)
    fmt.Println(person)

    new_json, _ := json.Marshal(person)
    fmt.Printf("%s\n", new_json)
}

// *Output*
// &{John Smith }
// {"first_name":"John","last_name":"Smith"}

The json package can look at the tags for the field and be told how to map json <=> struct field, and also extra options like whether it should ignore empty fields when serializing back to json.

Basically, any package can use reflection on the fields to look at tag values and act on those values. There is a little more info about them in the reflect package
http://golang.org/pkg/reflect/#StructTag :

By convention, tag strings are a concatenation of optionally space-separated key:"value" pairs. Each key is a non-empty string consisting of non-control characters other than space (U+0020 ' '), quote (U+0022 '"'), and colon (U+003A ':'). Each value is quoted using U+0022 '"' characters and Go string literal syntax.

@Ismail Badawi 2012-06-02 01:57:56

Kind of like Java annotations?

@jdi 2012-06-02 02:06:34

@isbadawi: I'm not a java guy, but at quick glance of the definition of java annotations, yes it seems they are achieving the same goal; attaching metadata to elements that can be examined at runtime.

@Matt Joiner 2012-06-04 04:28:29

FWIW the same can be done for XML in Go too.

@sat 2014-05-21 04:23:08

Not really java annotations. Java annotations are type safe and compile time checked - not string literals like go. Java annotations are much more powerful and robust than golang basic metadata provisions.

@Eno 2014-10-06 18:08:56

As part of the MongoDB driver for Go, mgo, also uses tags in its bson package (which can also be used by itself). It gives you precise control over what BSON is generated. See godoc.org/labix.org/v2/mgo/bson#pkg-files

@Max Heiber 2015-06-12 04:04:10

Are there other examples besides JSON and BSON?

@jdi 2015-06-12 05:27:40

This flag parsing package that I like to use makes use of struct tags for defining your flag options: godoc.org/github.com/jessevdk/go-flags

Related Questions

Sponsored Content

21 Answered Questions

[SOLVED] What is reflection and why is it useful?

15 Answered Questions

[SOLVED] what should be the values of GOPATH and GOROOT?

  • 2011-11-01 17:32:52
  • jshen
  • 284728 View
  • 278 Score
  • 15 Answer
  • Tags:   go

7 Answered Questions

[SOLVED] What is an idiomatic way of representing enums in Go?

  • 2013-01-20 16:07:22
  • carbocation
  • 244633 View
  • 457 Score
  • 7 Answer
  • Tags:   enums go genetics

30 Answered Questions

[SOLVED] What are the differences between struct and class in C++?

12 Answered Questions

[SOLVED] How to convert a zero-terminated byte array to string?

  • 2013-01-09 07:19:48
  • Derrick Zhang
  • 453949 View
  • 467 Score
  • 12 Answer
  • Tags:   go

2 Answered Questions

[SOLVED] How to define multiple name tags in a struct

  • 2013-09-05 11:56:28
  • Sofia
  • 32081 View
  • 112 Score
  • 2 Answer
  • Tags:   json struct go

13 Answered Questions

[SOLVED] What is the difference between instanceof and Class.isAssignableFrom(...)?

13 Answered Questions

[SOLVED] What could cause java.lang.reflect.InvocationTargetException?

1 Answered Questions

[SOLVED] Golang Reflection: Get Tag from struct field

Sponsored Content