Middle · Architecture and systems

A number without units crosses an API boundary

An API accepts timeout: 500 and a monetary amount as float64. What questions must be resolved before implementing it?

Try explaining this aloud before opening the answer. State your assumptions and trace a boundary case.

EXAMPLE · FRAGMENT UNLESS A COMPLETE PROGRAM IS SHOWN

go
package main

import (
	"fmt"
	"math/big"
	"time"
)

type Cents int64

func main() {
	timeout := 250 * time.Millisecond
	price := Cents(199)
	raw, ok := new(big.Int).SetString("1000000000000000001", 10)
	if !ok {
		panic("invalid integer")
	}
	copied := new(big.Int).Set(raw)
	copied.Add(copied, big.NewInt(1))
	fmt.Println(timeout, price, raw.String(), copied.String())
}
Reveal a strong answer
  1. An int64 does not tell the next engineer whether it represents milliseconds, Unix seconds, cents or token base units. A float64 cannot represent every decimal amount exactly. At API boundaries, define units, range, rounding and whether a missing field differs from zero. Inside the program, use types and constructors that make those contracts difficult to confuse.

  2. Use time.Duration for elapsed budgets and time.Time for instants. Calendar schedules need a named location and explicit daylight-saving behavior. Go time values may contain a monotonic component for local elapsed measurements; serialization does not preserve that local clock reading. Use integer base units or a reviewed decimal package for money and validate scaling at the input boundary. The duration is explicitly milliseconds, the amount is cents, and the large token amount is parsed without a floating-point round trip. big.Int operations mutate their receiver, so Set makes the independent copy before adding. The example demonstrates representation only; currency conversion, decimal formatting and overflow policy still need explicit rules.

  3. Do not guess units from a JSON number or infer token decimals from a symbol. A pointer or optional type may distinguish omitted from zero. Check overflow before multiplication in fixed-width money types. Test rounding boundaries, negative amounts, maximum values, different decimal scales, a daylight-saving transition and serialization/restart of timestamps.

Common trap

Changing float64 to int64 without defining scale and range does not fix the contract.

Try it

Specify duration units, omitted-versus-zero behavior, range, monetary base units and decimal rounding; include timestamp serialization.

Worked solution

The wire contract needs explicit units and presence. Parse durations into a validated time.Duration and exact monetary text into the intended integer/decimal representation without a float intermediate. Define scale, rounding and overflow before conversion. Distinguish wall-clock instants, local elapsed budgets and calendar schedules; serialized time does not preserve the process-local monotonic component. Test boundaries and restart/serialization behavior.

Change the constraint

How would two tokens with the same symbol but different networks or scales change the identity model?

How did you do?

Self-assessment, not a compiler pass or interview score. Explain the reasoning unaided before marking understood.

Not marked. Progress stays on this browser, separate from course completion.

Primary references

Checked 2026-10-28. Use documentation for your pinned runtime, driver and tool version.