In Go, what is a time.Duration and how do you express a three-second value?
answer
- it is a number, not a struct
- one integer, one fixed unit
- int64 of nanoseconds
- multiply by a unit constant
- 3 * time.Second, 500 * time.Millisecond
basics
~20 sA time.Duration is an int64 count of nanoseconds, not a struct, so durations are plain numbers you can add, subtract and compare. Write three seconds as 3 * time.Second, multiplying by one of the time package's unit constants.
solid answer
~40 s`time.Duration` is declared as `type Duration int64`, and the integer it holds is a count of nanoseconds. The `time` package exports unit constants — `time.Nanosecond`, `time.Microsecond`, `time.Millisecond`, `time.Second`, `time.Minute`, `time.Hour` — so you build a value by multiplying: `3 * time.Second`, `500 * time.Millisecond`, `2*time.Hour + 30*time.Minute`. That multiplication works because `3` is an untyped constant that takes on the `Duration` type; an `int` variable does not, so `n * time.Second` will not compile and you write `time.Duration(n) * time.Second`. Because a Duration is an integer, the ordinary arithmetic and comparison operators work on it directly. To get a plain number back out, use the methods — `d.Seconds()` returns a `float64`, `d.Milliseconds()` an `int64` — rather than a conversion, because `int64(d)` gives nanoseconds. Printing a Duration shows its `String()` form, such as `1h30m0s`.
code
go · 10 linestimeout := 3 * time.Second
fmt.Println(timeout) // prints: 3s
fmt.Println(int64(timeout)) // prints: 3000000000
n := 3
// timeout = n * time.Second // compile error: mismatched types int and time.Duration
timeout = time.Duration(n) * time.Second
lease := 2*time.Hour + 30*time.Minute
fmt.Println(lease) // prints: 2h30m0sgo deeper
Be ready to say a Duration is an int64 of nanoseconds and to write 3 * time.Second, 500 * time.Millisecond and 2time.Hour + 30time.Minute without hesitating.
Explain why an untyped constant multiplies with time.Second while an int variable needs time.Duration(n), and name the methods that convert a Duration back to a number.
Show judgment about where durations enter a service — configuration, flags, computed spans — and insist on Duration-typed values rather than bare ints whose unit lives only in a variable name.
Own the convention across teams: timeouts and intervals in config files and exported APIs are time.Duration, never an int of unstated milliseconds, so the unit cannot be lost at a service boundary.
## The type is a number, not a record In Go's standard library the type is declared as: type Duration int64 That is the whole story about its representation. A `time.Duration` is a single 64-bit signed integer, and the unit of that integer is **nanoseconds**. It does not hold a start instant, an end instant, a unit field, or a calendar component. `time.Duration(1500000000)` and `1500 * time.Millisecond` and `1.5 * float64` converted appropriately all denote the same thing: 1,500,000,000 nanoseconds. This is different from the duration types in many other languages, which are structs or objects carrying an amount plus a unit. Go collapses that to one integer with a fixed unit, which is why duration arithmetic in Go is just integer arithmetic. ## Building a duration The package exports one constant per unit: - `time.Nanosecond` = 1 - `time.Microsecond` = 1000 * Nanosecond - `time.Millisecond` = 1000 * Microsecond - `time.Second` = 1000 * Millisecond - `time.Minute` = 60 * Second - `time.Hour` = 60 * Minute Notice where the list stops. There is no `time.Day` and no `time.Week`, because a calendar day is not a fixed number of nanoseconds everywhere — that kind of arithmetic belongs to `time.Time.AddDate`, not to `Duration`. You compose values by multiplying and adding: timeout := 3 * time.Second poll := 500 * time.Millisecond lease := 2*time.Hour + 30*time.Minute ## Why an untyped constant works and an int variable does not Go has no implicit conversion between named integer types. `3 * time.Second` compiles because `3` is an *untyped constant*: it has no type of its own until context gives it one, and the context here is `time.Duration`, so it becomes a Duration constant. Write the same thing with a variable and it fails: n := 3 d := n * time.Second // invalid operation: mismatched types int and time.Duration The fix is an explicit conversion of the number, not of the constant: d := time.Duration(n) * time.Second A very common bug is to convert the wrong way round — `time.Duration(n)` on its own means *n nanoseconds*, which for `n := 3` is three nanoseconds, not three seconds. Always multiply by the unit you mean. ## Getting a number back out Because the underlying type is `int64`, a conversion is legal but almost never what you want: - `int64(d)` — nanoseconds. Correct, but easy to misread as "the number of whatever unit I was thinking of". - `d.Nanoseconds()`, `d.Microseconds()`, `d.Milliseconds()` — `int64`, truncated toward zero. - `d.Seconds()`, `d.Minutes()`, `d.Hours()` — `float64`, so fractions survive. Dividing by a unit constant also works and is idiomatic when you want a whole number of units: `d / time.Millisecond` yields a `Duration` whose value is the count of milliseconds, so it usually appears wrapped, as `int64(d / time.Millisecond)`. ## Arithmetic and comparison Since it is an integer type, everything you expect works: `a + b`, `b - a`, `d * 2`, `d / 2`, `a < b`, `a == b`. Multiplying two durations together is legal Go but meaningless (nanoseconds squared), so treat `d1 * d2` as a bug. Durations can be negative — `time.Until(t)` for a past `t` returns a negative value, and `-1 * time.Second` is fine. The range is the range of `int64` nanoseconds: roughly ±292 years. That is plenty for timeouts and elapsed measurements and not enough for calendar spans, which is another reason calendar work uses `time.Time` and `AddDate`. ## Printing `Duration` implements `String()`, and the format is a human-readable sum of units with the largest unit first: `1h30m0s`, `1.5s`, `500ms`, `0s`. `fmt.Println(3 * time.Second)` therefore prints `3s`, not `3000000000`. This is why durations read well in logs without any formatting work, and why a log field that shows a raw nanosecond count is a sign someone converted to `int64` on the way out. ## Where durations come from You rarely type them all by hand. `time.Time.Sub`, `time.Since` and `time.Until` return durations; `time.ParseDuration` builds one from a string such as `"1h30m"`; `flag.Duration` reads one from the command line. The value you get from any of them is the same plain int64 of nanoseconds, so it composes with everything above.
- Why does `n * time.Second` fail to compile when `n` is an `int` variable, and what is the fix?Go has no implicit conversion between named types, so an `int` variable and a `time.Duration` cannot be multiplied. The literal `3` works only because an untyped constant adopts the Duration type from context. Convert the number explicitly and multiply by the unit: `time.Duration(n) * time.Second`. Writing `time.Duration(n)` alone means n nanoseconds, which is the usual off-by-a-billion bug.
- How would you log a duration as a whole number of milliseconds?Call `d.Milliseconds()`, which returns an `int64` truncated toward zero. `int64(d / time.Millisecond)` is equivalent and also idiomatic. What you must not do is `int64(d)` — that is nanoseconds, and it silently produces a number a million times too large. If you want fractions, `d.Seconds()` returns a `float64`.
- What is the largest span a `time.Duration` can represent?About 292 years in either direction, because it is an int64 of nanoseconds. `time.Time.Sub` saturates rather than wrapping: if the gap between two instants exceeds the range, it returns the maximum or minimum Duration. For spans measured in years, keep working with `time.Time` values and calendar arithmetic instead of durations.
saying these in an interview costs you the question
- Calls time.Duration a struct holding a start and an end
- Thinks int64(d) yields seconds rather than nanoseconds
- Writes time.Second(3) as though the constant were a function
- Expects n * time.Second to compile for an int variable
- Uses time.Duration(3) expecting three seconds
- Assumes printing a Duration shows the raw nanosecond count