Standard library patterns · 3 MIN READ
Struct tags are the JSON schema
Control field names, omit empties, and know what unmarshalling leaves untouched.
encoding/json maps struct fields by name, and a tag overrides that. Only exported fields are considered, which is the first thing that catches people: a lower-case field is invisible to the encoder with no error.
Unmarshal leaves fields absent from the input untouched rather than zeroing them, so decoding into a reused struct can silently keep old values.
SEE THE IDEA
Exported fields and tags define the wire representation
- 01
Go value
gotype Config struct { Name string }Only exported fields are considered
- 02
Field tag
go`json:"name,omitempty"`Controls naming and omission
- 03
JSON bytes
gojson.Marshal(config)Encoding can return an error
Decoding into an existing value can preserve fields absent from the input.
In practice
Treat tags as part of the external contract and test representative encoded values. Decode into a fresh struct when missing fields should become zero. Use a pointer field when an absent field must be distinguished from a present zero, and consider DisallowUnknownFields for strict input.
Watch out
Do not silently ignore Marshal or Unmarshal errors. Lowercase fields remain invisible even if they carry a json tag.
Read and predict
package main
import (
"encoding/json"
"fmt"
)
type Config struct {
Host string `json:"host"`
Port int `json:"port,omitempty"`
secret string
}
func main() {
data, _ := json.Marshal(Config{Host: "localhost", secret: "hidden"})
fmt.Println(string(data))
}What is printed, and where did port and secret go?
Trace each value and write down your reasoning. Copy the source into GopherForge or your local Go environment to compile and check it. This web page does not execute your code or send it to a compiler service.
Progress stays in this browser. No account needed.