Day 013 — Structs & Struct Tags¶
Month 1 · Week 2 · ⬅ Day 012 · Day 014 ➡ · Journal index
🎯 Learning Objective¶
Declare structs, choose value vs pointer semantics, embed for composition, and drive JSON with struct tags.
📚 Topics¶
- Struct declaration & value semantics
- Embedding (composition over inheritance)
- Struct tags +
encoding/json
📖 Reading / Sources¶
- Learning Go ch.3 (Structs) & ch.7 (Types/Methods)
- Go Blog — JSON and Go
- pkg.go.dev —
encoding/jsonMarshal
📝 Notes¶
- A struct is a fixed set of named fields. Structs are values: assignment/passing copies all fields → [[struct-value-semantics]].
- Two structs are comparable with
==only if all fields are comparable (no slice/map/func fields). - Embedding an anonymous field promotes its fields/methods to the outer struct — composition, not inheritance → [[embedding]].
- Method receivers: a pointer receiver can mutate the struct and avoids copying; a value receiver gets a copy. Be consistent per type; if any method needs a pointer receiver, give them all pointer receivers → [[receivers]].
- Struct tags are string metadata read via reflection. For
encoding/json:json:"name"renames,json:",omitempty"drops zero values,json:"-"excludes the field → [[struct-tags]]. - Only exported (capitalized) fields are marshaled/unmarshaled; unexported fields are invisible to
encoding/json→ [[exported-fields]]. encoding/jsonignores unknown keys on Unmarshal by default; pass a pointer (&v) so it can write into your value.- The empty struct
struct{}{}carries no data (0 bytes) — handy for set values and signal channels.
💻 Code Examples¶
type User struct {
Name string `json:"name"`
Email string `json:"email,omitempty"` // dropped when ""
Password string `json:"-"` // never serialized
Roles []string `json:"roles"`
}
func (u *User) AddRole(r string) { u.Roles = append(u.Roles, r) } // pointer: mutates
Full code:
examples/month-01/structs-tags/main.go· Run:go run ./examples/month-01/structs-tags
🏋️ Exercises / Practice¶
| Exercise | Status | Link |
|---|---|---|
| (reinforced via the structs-tags example) | ✅ | examples/month-01/structs-tags |
🐛 Mistakes Made¶
- Gave a method a value receiver and wondered why a field "wouldn't update" — it mutated a copy. Switched to a pointer receiver.
- Left a field lowercase and it vanished from JSON output (unexported → ignored).
❓ Open Questions¶
- When is embedding better than a named field? (When you want the inner type's methods promoted; otherwise use a named field for clarity.)
🧠 Active Recall (answer without looking)¶
- Q: What do
json:"-"andjson:",omitempty"do?A
- excludes the field entirely; ,omitempty omits it when it holds its zero value.
2. Q: Why can a value-receiver method not mutate the receiver? A
It operates on a copy of the struct; changes are discarded. Use a pointer receiver to mutate the original.
🪶 Feynman Reflection¶
A struct is a labeled record. Copying it copies every field, so to change the original a method must take a pointer. Tags are sticky notes on each field telling libraries like encoding/json how to name or skip it.
🕳️ Knowledge Gaps¶
- Custom
MarshalJSON/UnmarshalJSONand interfaces — revisit in the interfaces/methods week.
✅ Summary¶
I can define structs, pick value vs pointer receivers deliberately, compose with embedding, and control JSON output with struct tags.
⏭️ Next Steps / Prep for Tomorrow¶
- Day 014: Week 2 review + active recall.
| Time spent | Difficulty | Confidence |
|---|---|---|
| 90 min | 🟦🟦⬜⬜⬜ | 🟦🟦🟦⬜⬜ |
Suggested commit: feat(examples): structs and struct tags (day 013)