Structs, Tags and JSON
tally now has several facts per word: the word, its count, its share of the text. Passing three parallel values around is clumsy. A struct bundles them — and with a few tags, the same struct becomes tally --json output that other programs can read.
The rule
A struct groups fields; tags tell JSON the key; only capitals travel.
Structs. A struct type lists named, typed fields:
type WordStat struct {
Word string `json:"word"`
Count int `json:"count"`
Share float64 `json:"share,omitempty"`
note string
}Create values with field names (order-independent, and missing fields get zero values), then use dot access:
s := WordStat{Word: "go", Count: 3}
s.Count++ // 4
fmt.Println(s.Share) // 0Structs are values: t := s copies every field, just like arrays. Two structs of the same type compare with == when all their fields are comparable.
Tags are the back-quoted strings after a field's type. They do nothing by themselves; packages read them. encoding/json understands:
| Tag | Effect |
|---|---|
json:"word" |
use the key word |
json:"share,omitempty" |
leave the field out when it holds its zero value |
json:"-" |
never include this field |
| no tag | use the field name as the key, "Word" |
Only capitals travel. encoding/json can only see exported fields — names starting with a capital letter. note is invisible to it, tag or no tag.
data, err := json.Marshal(WordStat{Word: "go", Count: 3})
fmt.Println(string(data)) // {"word":"go","count":3}json.Unmarshal goes the other way, filling a struct from JSON; it matches keys to tags (or names) without caring about case.
The shortcut
To predict JSON output, walk the fields top to bottom and put each through three gates: exported? tag name? omitempty and zero?
Word
Exported, tag
word, not empty:"word":"go".
Drills
Answer fast — trust the rule.
A field is declared Total int with no tag. What key does json.Marshal use?
Which field would json.Marshal skip even with a tag json:"file"?
Count int has the tag json:"count,omitempty" and holds 0. What appears in the output?
a := WordStat{Word: "go"}; b := a; b.Word = "stop". What is a.Word?
Remember
- A struct groups fields; tags tell JSON the key; only capitals travel.
- Shortcut: each field through three gates — exported? tag name? omitempty and zero?
- Trap: a lower-case field never reaches the JSON, whatever its tag says.
