Weekly Review — Month 2 · Week 2 (Days 036–042)¶
📅 The Week in One Line¶
Assembled the standard library into a service-building toolkit: encoding/json (incl. struct tags & custom marshalers), the time package, the net/http client, context deadlines/cancellation, and log/slog structured logging.
✅ What I Completed¶
- Day 036 —
encoding/jsonMarshal & Unmarshal (+json-tagsexample) - Day 037 — struct tags & custom
Marshaler/Unmarshaler(+tempjsonexercise) - Day 038 —
time: durations, formatting, timers (+time-timersexample,humandurexercise) - Day 039 —
net/httpclient & requests (+http-contextexample) - Day 040 —
contexttimeouts & cancellation (+retryexercise) - Day 041 —
log/slogstructured logging (+slog-structuredexample) - Day 042 — Review & closed-book recall
- Runnable examples: 4 (
json-tags,time-timers,http-context,slog-structured) - Exercises solved: 3 (
tempjson,humandur,retry) — all with table-driven tests
💡 Lessons Learned¶
jsononly sees exported fields;Unmarshalneeds a pointer; numbers intointerface{}becomefloat64.- Custom JSON:
MarshalJSONcan use a value receiver, butUnmarshalJSONmust be a pointer receiver or it's silently ignored. Beware self-recursion insideMarshalJSON. time.Durationis nanoseconds; format/parse with the magic reference date2006-01-02 15:04:05; alwaysStop()aTicker.http.Get/DefaultClienthave no timeout; always closeresp.Body; a 404/500 is data, not a Go error.- A
contextonly signals — blocking code mustselectonctx.Done(); alwaysdefer cancel(); useerrors.IsforDeadlineExceeded/Canceled. slog: handler decides format/destination/level; prefer typed attrs over loose pairs;Withbuilds request-scoped child loggers.
💪 Strengths (what clicked)¶
- Struct tags and the
Marshaler/Unmarshalerescape hatch — the customCelsiusround trip felt natural. - The
context+httppairing: per-callWithTimeoutbound to a request viaNewRequestWithContext. slogtyped attributes and child loggers.
🧩 Weaknesses (what's still fuzzy)¶
json.RawMessageand partial/lazy decoding.time.Timer.Resetcorrectness (draining the channel) andRoundvsTruncateedge cases.- Tuning
http.Transport(connection pool, dial timeouts) beyondClient.Timeout. - Writing a custom
slog.Handlerthat injects a trace ID fromcontext.
🔁 Spaced-Repetition Re-quiz (topics from earlier weeks)¶
- Q: (Month 1)
nilslice vsnilmap — which is safe to use, which panics?A
Anilslice is safe toappendto andrange; writing to anilmap panics (reads return the zero value). - Q: (Month 2 W1) Why must you
Flushabufio.Writer?A
It buffers writes in memory; withoutFlushthe pending bytes never reach the underlying writer. - Q: (Month 2 W1) Which
fmtverb prints a value's Go-syntax form ignoringString()?A
%#v. - Q: (This week) Why must
UnmarshalJSONhave a pointer receiver?A
It must mutate the destination;jsononly invokes theUnmarshalerit finds on the addressable value, so a value receiver is never called and the field stays zero. - Q: (This week) Does a
ctxtimeout stop a runningtime.Sleep?A
No — context only signals viaDone(). Blocking work mustselectonctx.Done()or use a context-aware API; otherwise it runs to completion.
🎯 Action Items¶
- Refactor
http-contextfetch to decode JSON straight from the body withjson.NewDecoder. - Write a tiny custom
slog.Handlerthat pulls a request ID out ofcontext.Context. - Re-read the
timereference-layout table once more; drill three custom layouts from memory. - Add a
json.RawMessagemini-experiment for deferred decoding.
🚀 Next Week Goals¶
- Deep dive on
testing: table-driven subtests witht.Run,testing.Bbenchmarks +b.ReportAllocs(), fuzzing, and coverage. - The
gotoolchain end to end:go test/vet/build,gofmt/goimports, modules & versioning. - Apply this week's pieces in a small CLI/service that fetches JSON over HTTP with a context timeout and structured logs.
📊 Metrics¶
| Hours | Days hit | Exercises | Commits | Avg confidence |
|---|---|---|---|---|
| 10.5 | 7/7 | 3 | 7 | 3.⅗ |
Suggested commit: docs(journal): month 2 week 2 review