Reputation: 4811
How are these various validation libraries adding this meta data to structs like:
type Post struct {
Title string `valid:"alphanum,required"`
Message string `valid:"duck,ascii"`
AuthorIP string `valid:"ipv4"`
Date string `valid:"-"`
}
I'm confused, the property is Title, the type is string. Beyond that how can you just add valid:"alphanum,required"
Is this using reflection?
Is this like attributes in other languages?
[Required]
public int Title { get;set; }
Upvotes: 6
Views: 7153
Reputation: 3228
Those are tags. From the language spec (towards the end of Struct types):
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 and take part in type identity for structs but are otherwise ignored.
As per the quote above, you can use them with reflection.
ALso , from the reflect package doc:
A StructTag is the tag string in a struct field.
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.
There is an excellent executable example at the link above.
Tags are also used extensively with json. From the json package docs:
The object's default key string is the struct field name but can be specified in the struct field's tag value. The "json" key in the struct field's tag value is the key name, followed by an optional comma and options.
Loads of additional data on that page.
This earlier question may also be helpful.
Upvotes: 2
Reputation: 36279
Go doesn't have attributes in general sense. The strings in the struct are struct 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 and take part in type identity for structs 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" }
You can't add or change them, but you can access them using the reflect
package.
Another thing that kinda looks like attributes are "magic comments" like
// +build amd64
or
//go:noinline
These are compiler-specific and IIRC are not a part of the language specification.
Upvotes: 5