skip to content

Text, Time and Collections

The standard library packages you touch every day for text, time and collections, where the idiomatic call and its allocation behaviour matter more than the API list.

part ofGo (Golang)overview, primer and where to startread it →
on this pageshow

explore

questions

129 · 7 sections

Why is strings.Builder preferred over `+=` when assembling a string in a Go loop?

level: juniorimportance: must knowfreq 68%
basics
~20 s

Go strings are immutable, so each += builds a brand-new string and copies everything accumulated so far. strings.Builder appends into one growable byte slice instead, and its String method hands those bytes over as a string without a final copy.

open as a page

What is the difference between strings.Split(s, " ") and strings.Fields(s) when splitting a line into words?

level: juniorimportance: must knowfreq 70%
basics
~20 s

strings.Split cuts at every single separator, so a run of two spaces produces an empty string between them. strings.Fields treats any run of one or more Unicode whitespace characters as one separator and never returns an empty element.

open as a page

In Go, how does strings.Trim's cutset differ from strings.TrimPrefix's prefix?

level: juniorimportance: must knowfreq 72%
basics
~20 s

strings.Trim takes a cutset: a set of individual characters, stripped repeatedly from both ends in any order. strings.TrimPrefix takes a literal string and removes it once from the front, returning the input unchanged when that prefix is absent.

open as a page

Which Go standard library call counts the runes in a string, and why can its result surprise a user?

level: juniorimportance: must knowfreq 72%
basics
~20 s

utf8.RuneCountInString from the unicode/utf8 package returns the number of Unicode code points in a Go string. It can still surprise: accented letters, emoji and flags are often several code points that a user sees as one character.

open as a page

When would you reach for bytes.Buffer instead of strings.Builder in Go?

level: middleimportance: should knowfreq 52%
basics
~20 s

Reach for bytes.Buffer when you need to read the accumulated bytes back, hand them to something expecting an io.Reader, or keep the capacity across a Reset. Use strings.Builder when the result is a string: its String method avoids the final copy.

open as a page

In Go's fmt, how do the %f, %e and %g verbs differ when printing a float64?

level: juniorimportance: must knowfreq 62%
basics
~20 s

%f prints decimal digits with no exponent, %e prints scientific notation, and %g picks between them by magnitude. %f and %e default to six digits after the point; %g defaults to the shortest digits that identify the value uniquely.

open as a page

What does strconv.Atoi return when the input string is not a valid integer?

level: juniorimportance: must knowfreq 82%
basics
~20 s

strconv.Atoi returns two values, the parsed int and an error. On bad input it returns 0 plus a non-nil error rather than panicking, so the 0 is meaningless until you have checked that the error is nil.

open as a page

In Go, how do the fmt verbs %v, %+v and %#v differ when printing a struct?

level: juniorimportance: must knowfreq 78%
basics
~10 s

%v prints only a struct's field values, like {s-42 <nil>}. %+v adds the field names. %#v prints a Go-syntax literal with the package-qualified type name and quoted strings, like main.Session{ID:"s-42"}.

open as a page

Why does strconv.FormatFloat with precision -1 round-trip exactly through ParseFloat?

level: middleimportance: must knowfreq 48%
basics
~20 s

Precision -1 makes strconv.FormatFloat emit the fewest digits that no other float64 shares, so strconv.ParseFloat reads the string back as the identical value. Any fixed precision can print a string that parses back as a different number.

open as a page

When does fmt call a type's String() method, and why can a pointer receiver hide it?

level: middleimportance: must knowfreq 66%
basics
~20 s

fmt calls String() when the operand satisfies fmt.Stringer and the verb is %v, %s, %q, %x or %X. If String has a pointer receiver, only *T satisfies the interface, so printing a T value falls back to default formatting.

open as a page

In Go's regexp package, when should you use regexp.MustCompile instead of regexp.Compile?

level: juniorimportance: must knowfreq 72%
basics
~20 s

regexp.MustCompile panics if the pattern is invalid and returns only a *regexp.Regexp, so it suits patterns written as literals in your source, normally as a package-level var. Use regexp.Compile, which returns an error, for any pattern supplied at runtime.

open as a page

Why does Go's regexp package reject lookaheads and backreferences?

level: juniorimportance: must knowfreq 60%
basics
~20 s

Go's regexp implements RE2 semantics: it simulates an automaton over the input instead of backtracking, so matching time stays bounded by input length times pattern size. Lookaheads and backreferences cannot be expressed in that model, so such patterns fail to compile.

open as a page

In Go's regexp package, what does FindStringSubmatch return for a match and for a non-match?

level: juniorimportance: must knowfreq 55%
basics
~20 s

FindStringSubmatch returns a []string in which element 0 is the entire matched text and elements 1..n are the capture groups, numbered by opening parenthesis. If the pattern matches nowhere in the input it returns nil, so check for nil before indexing.

open as a page

Why is regexp.MatchString(pattern, s) more expensive than calling MatchString on a compiled *regexp.Regexp?

level: middleimportance: should knowfreq 58%
basics
~20 s

The package-level regexp.MatchString compiles its pattern from scratch on every call and throws the compiled matcher away afterwards. The method runs on a *regexp.Regexp that was compiled once, so each call pays only for matching.

open as a page

In Go's regexp package, how do you turn on case-insensitive or dot-matches-newline matching?

level: middleimportance: should knowfreq 45%
basics
~20 s

Put the flag inside the pattern text: (?i) for case-insensitive, (?s) to let . match a newline. Go's regexp has no flags argument, so (?i), (?m), (?s) and (?U) written in the pattern are the only way to set modes.

open as a page

In a Go text/template, what does {{.Name}} resolve against, and how do Parse and Execute fit together?

level: juniorimportance: must knowfreq 72%
basics
~20 s

Dot is the current data value, so {{.Name}} reads a Name field, map key or method from it. Parse compiles the template text once; Execute applies it to one data value and writes the output.

open as a page

In Go's html/template, what do the {{define}} and {{template}} actions do, and when do you need ExecuteTemplate rather than Execute?

level: juniorimportance: must knowfreq 46%
basics
~20 s

{{define "name"}}...{{end}} names a template inside the parsed text; {{template "name" .}} renders it in place with the data you give it. Execute runs the receiver template; ExecuteTemplate picks one associated template from the set by name.

open as a page

What does html/template escape automatically that text/template leaves untouched?

level: juniorimportance: must knowfreq 60%
basics
~20 s

html/template escapes every value it substitutes, choosing the escaping from where the value lands in the page: HTML text, an attribute, a script block or a URL. text/template escapes nothing and writes the value as-is.

open as a page

Why must a Go template's Funcs call come before Parse when the template calls a custom function?

level: juniorimportance: must knowfreq 55%
basics
~20 s

Parsing resolves every function name against the template's func map. Register the helper after Parse and the parser has never heard of it, so Parse fails with a "function not defined" error instead of failing later at Execute.

open as a page

Inside {{range .Items}} in a Go template, what happens to dot, and how do you reach the top-level value?

level: middleimportance: must knowfreq 60%
basics
~20 s

Inside a range body dot is rebound to the current element, so outer fields are unreachable through it. Use $, which stays bound to the value passed to Execute, or capture what you need in a variable before the loop.

open as a page

Why does Go's time formatting use the layout string "2006-01-02" instead of a pattern like "yyyy-MM-dd"?

level: juniorimportance: must knowfreq 78%
basics
~20 s

Go has no pattern letters. A layout is one fixed reference instant, Mon Jan 2 15:04:05 MST 2006, written in the shape you want output. So 2006 means year, 01 month, 02 day, 15 hour, 04 minute, 05 second.

open as a page

What two clock readings does Go's time.Now() put into one time.Time, and which one does time.Since use?

level: juniorimportance: must knowfreq 50%
basics
~20 s

time.Now() returns a time.Time holding both a wall-clock reading, which tells the calendar date and time and can be stepped by the system, and a monotonic reading, which only moves forward. time.Since subtracts using the monotonic reading.

open as a page

In Go, what is a time.Duration and how do you express a three-second value?

level: juniorimportance: must knowfreq 78%
basics
~20 s

A 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.

open as a page

What do time.UTC, time.Local and t.In(loc) mean for a Go time.Time value?

level: juniorimportance: must knowfreq 52%
basics
~20 s

A time.Time carries an instant plus a pointer to a time.Location that decides how its calendar fields print. time.UTC and time.Local are two such locations, and t.In(loc) returns the same instant displayed in loc, not a different point in time.

open as a page

What zone does time.Parse assign when the input carries no offset, and how does time.ParseInLocation differ?

level: middleimportance: must knowfreq 60%
basics
~20 s

time.Parse returns a time in UTC whenever the value carries no zone offset or abbreviation, so a local wall-clock string is silently read as UTC. time.ParseInLocation reads the same digits as wall-clock time in a *time.Location you supply.

open as a page

What does Go's cmp.Compare return, and which types can you call it on?

level: juniorimportance: must knowfreq 42%
basics
~10 s

cmp.Compare returns -1 if the first argument is less, 0 if they are equal, and +1 if it is greater. It accepts any cmp.Ordered type: integers, floats, strings, and named types built on them.

open as a page

In Go's container/heap, which five methods must your type implement?

level: juniorimportance: must knowfreq 34%
basics
~20 s

container/heap.Interface embeds sort.Interface, so your type needs Len, Less and Swap, plus Push(x any) to append one element and Pop() any to remove and return the last one. Five methods, and you own the storage.

open as a page

Why does ranging over a Go map yield a different order each run, and how do you produce stable output?

level: juniorimportance: must knowfreq 78%
basics
~10 s

Go deliberately randomises map iteration, so no order is guaranteed or repeatable. For stable output, copy the keys into a slice, sort that slice, then read the map in that key order.

open as a page

What does slices.Clone(s) copy that the plain assignment b := s does not?

level: juniorimportance: must knowfreq 68%
basics
~10 s

slices.Clone allocates a new backing array and copies the elements into it, so the two slices no longer share storage. Plain assignment copies only the slice header, leaving both names pointing at one array.

open as a page

What does slices.Sort do to a slice, and which element types can it sort?

level: juniorimportance: must knowfreq 62%
basics
~20 s

slices.Sort reorders a slice in place into ascending order and returns nothing. It is generic over element types that support the less-than operator - integers, floats and strings - so no comparison callback or interface implementation is needed.

open as a page

In Go's `maps` package, what does `maps.Keys(m)` return, and how do you turn it into a slice?

level: juniorimportance: must knowfreq 52%
basics
~10 s

maps.Keys returns an iterator of type iter.Seq[K], not a slice. You can range over it directly, or convert it with slices.Collect(maps.Keys(m)) to get a []K. slices.Sorted(maps.Keys(m)) collects and sorts in one call.

open as a page

What does iter.Pull return, and why use it instead of ranging over an iter.Seq?

level: juniorimportance: must knowfreq 40%
basics
~20 s

iter.Pull(seq) returns two functions: next, which gives the next value plus a bool that is false once the sequence is exhausted, and stop, which ends it early. It turns a sequence into a cursor you advance yourself.

open as a page

How do you write a Go function returning iter.Seq[string] that a caller can use in a for-range loop?

level: juniorimportance: must knowfreq 40%
basics
~20 s

Return a closure whose type is func(yield func(string) bool). Inside it, call yield once per element and stop the moment yield returns false. Ranging over the returned function makes the compiler supply yield from the loop body.

open as a page

What is Go's `iter.Seq[V]` type, and what does a value of that type actually hold?

level: juniorimportance: must knowfreq 62%
basics
~20 s

iter.Seq[V] is a function type: func(yield func(V) bool). An iterator is just a function that calls yield once per element, and each yield call becomes one iteration of the for range loop that consumes it.

open as a page

In an iter.Seq iterator you wrote, what must happen when the yield callback returns false, and what if it keeps going?

level: middleimportance: must knowfreq 55%
basics
~20 s

A false result from yield means the consuming loop has stopped. The iterator must produce no further values and return promptly, running its deferred cleanup. Calling yield again after it returned false is a run-time panic.

open as a page