10 — Maps & JSON
Two things Go gives you built in: a hash-table type (map) and struct-driven
JSON. Every example is live — edit it and press Run.
Maps and struct-tag JSON
A map is Go's built-in hash table, map[K]V. Reading a
missing key returns the value's zero value — so use the comma-ok form
(v, ok := m[k]) to tell "absent" from "present but zero". For JSON, you
declare a struct with field tags: only exported
(capitalised) fields are serialised, the tag sets the JSON key, and
omitempty drops a zero-valued field. Marshal and
Unmarshal convert both ways; unknown and missing fields are handled
gracefully.
package main
import (
"encoding/json"
"fmt"
)
type User struct {
Name string `json:"name"`
Age int `json:"age"`
Email string `json:"email,omitempty"` // dropped when empty
}
func main() {
m := map[string]int{"x": 0}
v, ok := m["x"]
fmt.Println(v, ok) // 0 true — present but zero
v, ok = m["missing"]
fmt.Println(v, ok) // 0 false — absent
b, _ := json.Marshal(User{Name: "andy", Age: 40, Email: "a@example.com"})
fmt.Println(string(b))
b, _ = json.Marshal(User{Name: "a", Age: 1})
fmt.Println(string(b)) // email omitted
var u User
json.Unmarshal([]byte(`{"name":"cara","age":22,"extra":true}`), &u)
fmt.Printf("%s %d %q\n", u.Name, u.Age, u.Email) // extra ignored, email zero
}
Output:
0 true
0 false
{"name":"andy","age":40,"email":"a@example.com"}
{"name":"a","age":1}
cara 22 ""
Unmarshal takes the address (&u) so it can fill
the struct in. One trap: the zero value of a map is nil, and writing to a
nil map panics — initialise with map[K]V{} or make first.
Ranging a map visits entries in randomised order.
Recap
| Concept | In Go |
|---|---|
| Map | map[K]V — built-in hash table |
| Present vs absent | Comma-ok: v, ok := m[k] |
| Nil map | Reads OK; writing panics — initialise first |
| JSON key | Struct tag `json:"key"` (field must be exported) |
| Drop zero fields | json:"key,omitempty" |
| Encode / decode | json.Marshal(v) / json.Unmarshal(data, &v) |
Next: 11 — defer, panic & recover.