Your country

Tools that support it use your country for local currency, number formats, units and paper size. Your choice is saved only in this browser.

Type a name or a two-letter code. Use the up and down arrow keys to move through the countries, Enter to choose one and Escape to close.

Go Module 11

Generics, including generic methods (1.27) interview questions

Interview questions on generics, including generic methods (1.27): warm-ups, then what each harder question tests and how a good answer starts.

22 questions: 6 warm-ups and 16 with model answers · Levels: Fresher to staff

Warm-up questions

Short questions with short answers, each answered in full.

  1. Fresher

    What is the difference between a type parameter and a type argument in Go?

    Answered in the lesson Type parameters: generic functions and inference

  2. Fresher

    What does the ~ in a Go constraint such as ~int mean?

    Answered in the lesson Constraints, type sets and cmp.Ordered

  3. Fresher

    How do you return "nothing" from a method of a generic type such as Stack[T]?

    Answered in the lesson Generic types, data structures and type aliases

  4. Fresher

    What did Go 1.27 change about methods and type parameters?

    Answered in the lesson Generic methods in Go 1.27

  5. Mid

    What is a self-referential constraint in Go?

    Answered in the lesson Advanced generics: inference and self-reference

  6. Mid

    How does the Go compiler implement generics?

    Answered in the lesson Generics in practice: performance and API design

Questions with model answers

What each question tests, the first step of a good answer and the follow-ups to expect.

  1. Mid to senior

    A pull request changes func Send(n Notifier, msg string) error into func Send[N Notifier](n N, msg string) error, and its description says that type parameters make the call faster. Review the change: what do you ask for, and what do you suggest?

    What it tests
    Knowing when a type parameter adds nothing, how the gc compiler builds generic code, and asking for a benchmark before accepting a claim about speed.
    First step
    Point out that Send only calls a method of n, the case the Go blog gives to interfaces, and that the generic version still calls Notify indirectly. Ask for a b.Loop benchmark of both versions with the real notifier types; until it shows a gain that matters, keep the interface, which is simpler to read and to fake.
    Follow-ups

    From the lesson Type parameters: generic functions and inference

    Model answer, Pro. Model answers open with any pass; prices are in the notice on this page.

    Opening the model answers with your pass…

    Model answers open with any MySmartCoPilot pass.

    • Pro pass · 1 week₹79$2.99
    • 30 days₹179$5.99
    • 1 year₹1,699$45

    One payment; a pass never renews. The price shown is the total you pay: no fees or charges are added at checkout.

    It also opens every other in-depth part in Learn and every Pro tool. Sales are final, except where the law gives you a right to withdraw, for example in the EU and the UK (refund policy).

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  2. Mid to senior

    A generic Dedupe[T comparable](xs []T) []T has passed its tests for a year. After a change feeds it values decoded from JSON into a []any, production logs show runtime error: hash of unhashable type []interface {}. Why did it compile, why does it panic, and how do you fix it?

    What it tests
    The type set of comparable, why interface types satisfy it since Go 1.20, which values make == and map keys panic, and fixes that move the check to compile time or to a key function.
    First step
    Explain that any satisfies comparable since Go 1.20, because == is defined on interface values, so the call compiled. The panic comes when a value inside holds a slice, which a nested JSON array decodes to, and Dedupe uses it as a map key. Then fix the design: dedupe on a comparable key, or decode into a concrete type.
    Follow-ups

    From the lesson Type parameters: generic functions and inference

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  3. Mid to senior

    RoundToRupee[T Number](p T) T, with Number being ~int | ~int64 | ~float64, fails with operator % not defined on p. A teammate proposes a type switch on any(p) inside the function, with math.Mod for the float case. What do you recommend instead, and why?

    What it tests
    Reading the error as a type-set problem, keeping constraints as small as the operations need, and knowing why a type switch on a type parameter undoes what the constraint was for.
    First step
    Explain the error: % must work for every type in Number's set, and float64 is in it. Then ask what the function is for. Money in paise is an integer, so narrow the constraint to ~int | ~int64 and keep % working; if floats really need rounding, give them their own function rather than a type switch inside a generic one.
    Follow-ups

    From the lesson Constraints, type sets and cmp.Ordered

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  4. Mid to senior

    A generic Max[T cmp.Ordered](xs []T) T over sensor readings returns different maxima for the same readings in a different order, and only in production, where some readings are NaN. Diagnose it, fix it, and say how a test would have caught it.

    What it tests
    Knowing that comparisons with NaN are false, why a > loop then depends on order, the documented NaN rules of cmp.Compare and slices.Max, and tests that put NaN in more than one position.
    First step
    Reproduce it first: run the same readings in two orders, one of them starting with NaN, and compare the results. Every comparison with NaN is false, so trace what a loop written with > does when the NaN is its first value and when it comes later. Then decide what a NaN should mean in this data before choosing how the comparison treats it.
    Follow-ups

    From the lesson Constraints, type sets and cmp.Ordered

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  5. Fresher to mid

    A generic Cache[K comparable, V any] has Get(k K) V, which returns the zero value on a miss. A service caches computed discounts, many of them 0, and its profile shows the discount recomputed on almost every request. Explain the cause and redesign the API.

    What it tests
    Seeing that the zero value of V cannot tell a miss from a stored zero, the (V, bool) convention, and how to change an exported method without breaking its callers.
    First step
    Show that Get returns 0 both for a miss and for a cached discount of 0, so the caller treats every zero as a miss and recomputes it. Then change the signature to Get(k K) (V, bool), as a map's comma-ok read and the lesson's cache do, and make callers branch on the bool.
    Follow-ups

    From the lesson Generic types, data structures and type aliases

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  6. Mid to senior

    Your team is moving a generic type Ledger[T] with 200 call sites from package billing to a new package, over several weeks. A colleague's first change declares type Ledger[T any] accounts.Ledger[T] in billing. Review it and plan the move.

    What it tests
    Knowing the difference between a generic alias and a generic definition, why identity and methods matter in a move spread over many changes, and the order of a safe migration.
    First step
    Point out the missing =: without it the line defines a new type rather than a second name for accounts.Ledger, so old and new code would hold two different types during the move. Ask for type Ledger[T any] = accounts.Ledger[T], a generic alias, with a Deprecated: note, so both names stay one type while callers move.
    Follow-ups

    From the lesson Generic types, data structures and type aliases

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes
  7. Mid to senior

    An LRU cache stores entries in container/list and reads e.Value.(*entry) on every Get. A colleague proposes a generic LRU[K comparable, V any] with its own linked list. What do you gain, what must the new version keep, and how do you show that it is correct?

    What it tests
    Typed nodes instead of type assertions, the map and doubly linked list that make Get and Put O(1), a constructor for a type whose zero value cannot work, and tests of eviction order.
    First step
    Name the gain: typed nodes remove the assertion on every read and turn a wrong key or value type into a compile error. Then list what must not change: Get, Put and eviction in constant time, and the order in which entries are evicted, which tests have to pin before and after the change.
    Follow-ups

    From the lesson Generic types, data structures and type aliases

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  8. Mid to senior

    A team replaces Config's Get(key string) (string, error) with a generic Get[T any](key string) (T, error). Code that passes a Config as a Source, an interface listing Get(key string) (string, error), stops compiling. Explain why, and design an API that keeps both.

    What it tests
    Knowing that a generic method never implements an interface method, why the language works that way, and the ways to keep a non-generic method at the interface while offering typed reads.
    First step
    Explain the error: Config now has only the generic Get, and an interface method can be matched only by a non-generic one, so Config no longer satisfies Source even though Get[string] has the right signature. Then keep Get(key) (string, error) for the interface and add the typed read under its own name, such as GetAs[T].
    Follow-ups

    From the lesson Generic methods in Go 1.27

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  9. Senior to staff

    Your library, used by many modules, exports MapList and FilterList as package functions. With Go 1.27 you want them as methods of List. Plan the release: what changes for callers, what about their go lines, and how do you move them over without breaking anyone?

    What it tests
    The language version that generic methods need, the effect of raising a library's go line on its users, deprecation instead of removal, and what go fix's inline directive does and does not rewrite.
    First step
    Say first that generic methods force the library's go line to 1.27, so every user must build with Go 1.27 or later; that is a release of its own, announced as such. Add the methods, keep MapList and FilterList as one-line wrappers marked Deprecated, and remove them only in a new major version.
    Follow-ups

    From the lesson Generic methods in Go 1.27

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  10. Mid to senior

    Review a Query[Row any] API with the methods Where(func(Row) bool) Query[Row], Select[V any](func(Row) V) []V and Sum() Row, which does not compile. Decide which operations stay methods, which become functions, and why.

    What it tests
    That a generic method takes its receiver's constraint as given, how its own type parameters can carry a constraint, and when a package function is still the clearer API.
    First step
    Start with the error: Sum needs + on Row, the method sees Row only with Query's own constraint, any, and a receiver cannot narrow it. Then sort the operations: the ones that work for every Row can stay methods, and the ones that need more of Row need another home.
    Follow-ups

    From the lesson Generic methods in Go 1.27

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  11. Mid to senior

    A reporting package defines Merger with Merge(Merger) Merger. Its callers are full of type assertions, and merging two different report types panics now and then. Propose a generic design for Go 1.26 or later, and say what it costs.

    What it tests
    Seeing why a method that takes and returns the interface loses the type, writing a self-referential constraint, and knowing what generics cannot express, such as a list that mixes types.
    First step
    Show the cost of the plain interface: Merge must accept any Merger, so each implementation asserts its argument, and every caller asserts the result back. Then replace it with type Mergeable[M Mergeable[M]] interface { Merge(M) M } and generic functions such as MergeAll[M Mergeable[M]], which return M and refuse mixed types while compiling.
    Follow-ups

    From the lesson Advanced generics: inference and self-reference

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  12. Mid to senior

    Users of your package's func Convert[From, To Number](xs []From) []To complain that every call must write both type arguments, as in Convert[int64, float64](fares). Explain why, and fix the API without breaking the code that already calls it.

    What it tests
    How partial type argument lists work, why a result-only type parameter belongs first, and how to change an exported generic function compatibly.
    First step
    Explain the cause: To appears only in the result, so it cannot be inferred, and a partial list can give only a prefix, which here is From. Reordering the parameters would break every existing Convert[int64, float64] call, so add a new function, To[Out, In Number](xs []In) []Out, and mark Convert deprecated.
    Follow-ups

    From the lesson Advanced generics: inference and self-reference

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  13. Senior to staff

    A generic LoadAll[T Loader](rows []Row) ([]T, error) calls t.Load(row) on each element of make([]T, len(rows)). Loader's Load has pointer receivers in every implementation. One team calls LoadAll[*Config] and gets nil pointer panics; another cannot compile LoadAll[Config]. Review and fix it.

    What it tests
    Method sets of T and *T, why a pointer type argument gives nil elements, the PT pattern with its inference, and when a function argument is the simpler design.
    First step
    Explain both failures from method sets and zero values: why Config does not satisfy Loader when every Load has a pointer receiver, and what make([]T, len(rows)) holds when T is *Config. Then look for a signature in which LoadAll creates real Config values and still calls Load on their addresses, with callers writing only the type they want back.
    Follow-ups

    From the lesson Advanced generics: inference and self-reference

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  14. Senior to staff

    A refactor turned a pricing loop over []Item into Total[T Pricer](items []T) int, which calls it.Price() on each element. Its benchmark is now about twice as slow, and the team suspects generics in general. Explain what is happening and what you would change.

    What it tests
    GC shapes and dictionaries, what a method call through a type parameter costs, reading the compiler's inlining report, and the function-argument design, all backed by repeated benchmarks.
    First step
    Separate the cases first: an operator on a basic shape costs nothing extra, but a method called on a T is left to the dictionary. Then compare the old loop and the new one in the compiler's inlining report, go test -gcflags=-m, and benchmark a version that takes the price function as an argument.
    Follow-ups

    From the lesson Generics in practice: performance and API design

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  15. Senior to staff

    A team fears that generics will make their binary large: a generic cache is instantiated with 40 value types, 30 of them pointer types and 10 structs. How many compiled copies of its methods should they expect, and how would you check the real number?

    What it tests
    Knowing that gc compiles one body per GC shape rather than per type, which types share a shape, and how to count the instantiations in a binary with go tool nm.
    First step
    Explain the rule: gc compiles one body per GC shape, and all 30 pointer types share one shape, so they cost one copy of each method between them. Structs share a shape only with types of the same underlying type, so the 10 structs may cost up to 10 copies. Then measure: build the binary and list the instantiated symbols with go tool nm.
    Follow-ups

    From the lesson Generics in practice: performance and API design

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 2 minutes
  16. Mid to senior

    A pull request adds Repository[K comparable, V Entity[K], S Store[K, V]], a Store interface with one in-memory implementation, and an Entity constraint, for a service that stores one kind of record. Review it: what do you ask to remove, what may stay, and how do you keep behaviour safe while it changes?

    What it tests
    The guideline to add type parameters when a second type needs the same code, interfaces with one implementation, and refactoring behind tests that pin the behaviour.
    First step
    Show that every type parameter is fixed to a single type at the only call, so none makes the code serve more types, and that Store has one implementation. Then ask what the service needs today, and which tests pin that behaviour, before anything is removed.
    Follow-ups

    From the lesson Generics in practice: performance and API design

    Model answer, Pro.

    In the answer:

    • Model answer
    • Follow-up answers
    • Common mistakes
    • Rubric
    • Variants
    • about 3 minutes

All Go interview questions · The Go track

Quick answers and tool search

Type to search tools or to get a quick answer, for example 18% of 2500. Use the up and down arrow keys to move through the results, Enter to choose, and Escape to close.