Core Language and Type System
Go is a small language whose interesting questions are about semantics: what a value copy actually copies, which method set satisfies an interface, and when the compiler demands a conversion.
part ofGo (Golang)overview, primer and where to startread it →on this pageshowhide
explore
- Types, Values and Constants29 questions
- Numeric Types and Overflow4 questions
- Operators and Evaluation Order4 questions
- Strings, Runes and Byte Slices4 questions
- Usable Zero Values4 questions
- Defined Types and Aliases5 questions
- Constants, Untyped Constants and iota4 questions
- Floating Point and NaN4 questions
- Slices, Maps and Structs24 questions
- Arrays vs Slices4 questions
- append and Slice Aliasing4 questions
- Maps: Semantics and Gotchas4 questions
- Pointers and Value Semantics4 questions
- Composite Literals and Builtins4 questions
- Shallow and Deep Copying4 questions
- Structs, Methods and Embedding25 questions
- Field Declaration and Tags4 questions
- Methods and Value vs Pointer Receivers5 questions
- Method Sets and Addressability Rules4 questions
- Promotion and Shadowing4 questions
- Embedding Is Not Inheritance4 questions
- Bound and Unbound Receivers4 questions
- Interfaces and Implicit Satisfaction27 questions
- Structural Typing Without Keywords4 questions
- Interface Values and the Typed-nil Trap4 questions
- Type Assertions, Type Switches and any4 questions
- Interface Design and Embedding5 questions
- Interface Dispatch Costs and Boxing5 questions
- Optional Capability Probing5 questions
- Generics and Type Parameters25 questions
- Type Parameters and Instantiation4 questions
- Constraints, Type Sets and comparable5 questions
- Writing Generic Functions and Containers4 questions
- Choosing Between Abstractions5 questions
- Inference and Its Limits4 questions
- Parametric Methods3 questions
- Functions, Closures and Control Flow25 questions
- Named Results and Comma-ok4 questions
- switch and Labeled Jumps5 questions
- Variadic Functions and Argument Passing4 questions
- Closures and Variable Capture4 questions
- defer Semantics and Ordering4 questions
- Loop Forms and range4 questions
- Packages and Visibility22 questions
- Exported and Unexported Names5 questions
- Imports, Aliases and Cycles4 questions
- Package Initialization Order and init()5 questions
- Scope and Shadowing Rules4 questions
- internal/ and cmd/ Layout4 questions
- Identity and Assignability12 questions
- Assignability and Conversions4 questions
- Comparability and Map Keys4 questions
- What nil Means4 questions
questions
189 · 8 sectionsIn Go, what happens when an int8 or a uint8 exceeds its maximum value?
basics
~20 sGo integers wrap around silently: an int8 holding 127 becomes -128 when incremented, and a uint8 holding 0 becomes 255 when decremented. There is no panic and no promotion to a wider type. Only constant overflow is caught at compile time.
What does iota do inside a Go const block, and what value does it start at?
basics
~20 siota is a built-in counter usable only in const declarations: it is 0 on the first line of a const block and increases by one on each following line. Every new const block resets it to 0.
In Go, what is the difference between type Celsius float64 and type Celsius = float64?
basics
~20 stype Celsius float64 declares a new, distinct type that shares float64's representation but has its own method set. type Celsius = float64 is an alias: Celsius and float64 are two names for one identical type.
Why does `const r = 1.0 / 0.0` fail to compile in Go while a float64 variable divided by zero yields +Inf?
basics
~20 sThe compiler evaluates constant expressions itself and rejects a constant division by zero outright. Float64 variables divide at run time under IEEE 754, so a nonzero value over zero gives positive or negative infinity, and zero over zero gives NaN.
In Go, what do the expressions -7/2 and -7%2 evaluate to, and what rule fixes the sign of the remainder?
basics
~10 sGo truncates integer division toward zero, so -7/2 is -3, and the remainder takes the sign of the dividend, so -7%2 is -1. The identity x == (x/y)*y + x%y always holds.
In Go, what is the difference between an array `[5]int` and a slice `[]int`?
basics
~20 sAn array's length is part of its type, and assigning or passing one copies every element. A slice is a resizable view onto a backing array, carrying a length and a capacity; copying a slice shares that array.
In Go, what is the difference between a keyed struct literal and a positional one?
basics
~20 sA keyed struct literal names each field and may omit fields, so order does not matter. A positional literal must supply every field in declaration order, so reordering fields silently changes what each value means.
In Go, how do you distinguish a missing map key from one whose stored value is zero?
basics
~20 sUse the two-value comma-ok form: v, ok := m[key]. ok is true only when the key is present. A one-value lookup returns the value type's zero value for a missing key, so 0, an empty string or false cannot tell you which happened.
Go passes every argument by value — how do you write a function that modifies the caller's struct?
basics
~20 sPass a pointer. A function parameter of type Player receives a copy, so writes to it die with the call. Declare the parameter as *Player, call it with &pl, and write p.HP = 40 — Go dereferences the selector for you.
In Go, what does embedding a struct type as an anonymous field promote to the outer struct?
basics
~20 sWriting a type inside a struct with no field name embeds it. The embedded type's fields and methods are promoted: you can use them directly on the outer value. The field itself is still named after its type.
In Go, does embedding a struct make the outer type usable wherever the embedded type is expected?
basics
~10 sNo. Embedding is composition, not subtyping: a struct that embeds StateRecord is its own distinct type and is never assignable to StateRecord. You pass the embedded value explicitly, as n.StateRecord.
Why does a T value fail to satisfy a Go interface whose methods have pointer receivers?
basics
~20 sGo's method set of T contains only methods declared with receiver T; methods declared with receiver *T belong to *T's method set alone. Interface satisfaction is checked against the method set, so only the pointer satisfies the interface.
What is a method value in Go, and what does `f := runner.Warmup` capture?
basics
~20 sA method value is the function value you get by writing runner.Warmup with no call parentheses. Go evaluates and saves the receiver at that moment, so calling f() later runs Warmup on that saved receiver and takes no receiver argument.
In Go, what is the difference between a value receiver and a pointer receiver on a method?
basics
~20 sA value receiver gets a copy of the value, so anything the method writes to it is discarded when the method returns. A pointer receiver gets the address of the caller's value, so its writes are visible afterwards.
In a Go type assertion, how do `v := x.(T)` and `v, ok := x.(T)` differ?
basics
~20 sThe one-result form v := x.(T) panics if the interface value x does not hold a T. The comma-ok form v, ok := x.(T) never panics: on a miss it yields T's zero value and sets ok to false.
What does calling a method through a Go interface value cost compared with calling it on the concrete type?
basics
~20 sAn interface method call is indirect: the target comes from the interface value's method table at run time, so the compiler cannot inline it or optimise across it. The lost inlining usually costs far more than the extra jump.
What does Go's io.ReadWriteCloser gain by embedding io.Reader, io.Writer and io.Closer?
basics
~20 sEmbedding folds the other interfaces' method sets into the new one, so io.ReadWriteCloser requires exactly Read, Write and Close and declares nothing extra. Any type with all three methods satisfies it automatically, with no declaration of intent.
How does a Go type come to satisfy an interface like io.Writer with no implements keyword?
basics
~20 sA Go type satisfies an interface just by having every method the interface lists, with matching names and signatures. Nothing is declared anywhere: the compiler checks the match at the point where the value is assigned to the interface.
What two parts does a Go interface value hold, and when is it equal to nil?
basics
~20 sA Go interface value holds two halves: a dynamic type and a value of that type. It is nil only when both halves are empty. An interface that has been given a type is non-nil even if the value stored is a nil pointer.
In Go generics, what is a type constraint, and what can a function do with a value of a type parameter constrained by any?
basics
~20 sA constraint is an interface that bounds a type parameter, defining which types may be used as the type argument. The any constraint admits every type, so the body may only assign, pass and store such values, not compare or add them.
When does Go infer a generic function's type arguments, and when must you write F[int] yourself?
basics
~20 sGo infers a generic function's type arguments from the ordinary arguments you pass at the call site. A type parameter that appears only in the result is not determined by any argument, so you must write it explicitly, as in Zeroint.
Why does a Go function that returns `any` push work onto every caller, and how does a type parameter remove it?
basics
~20 sReturning any gives the caller a value with no static type, so every call site must type-assert and can panic at run time. A type parameter returns the caller's own type instead, so the compiler checks the use.
In Go, what does the `[T any]` in `func Reverse[T any](s []T)` declare, and where can T be used?
basics
~20 sThe brackets declare a type parameter list. T is a placeholder for a type, constrained by any, so one Reverse serves every element type. T is in scope for the rest of the signature and the whole body.
When do you constrain a Go type parameter with comparable rather than cmp.Ordered, and what does each permit?
basics
~20 sUse comparable when the code needs equality: it is the predeclared constraint for types supporting == and !=, which is what a map key or set element requires. Use cmp.Ordered when the code needs ordering with <, >: integers, floats and strings.
In Go, does a function literal capture an outer variable's value at creation, or the variable itself?
basics
~20 sA Go function literal captures the variable itself, not a snapshot of its value. Assignments made after the literal is created are visible when it runs, and assignments made inside it are visible to the enclosing code.
In Go, what are the three non-range forms of for, and how do you write a while loop?
basics
~20 sGo's for has three non-range forms: three-clause (init; condition; post), condition-only, and infinite (for with no clauses at all). The condition-only form is Go's while loop - the language has no while and no do-while keyword.
What does Go's `defer` statement do, and when does the deferred call actually run?
basics
~10 sdefer postpones a function call until the surrounding function finishes, not until the enclosing block ends. Several deferred calls run in reverse registration order, last registered first, and they run on every return path.
In Go, how must a caller handle both results of a function returning `(int, bool)`?
basics
~10 sA Go call returning two values needs two targets: port, ok := parsePort(s). Write the blank identifier _ for any result you do not want. Binding one variable to it is a compile error.
In a Go switch statement, what happens at the end of a case body, and what does `fallthrough` do?
basics
~20 sIn Go a case body ends the switch automatically — there is no implicit fall-through and no break is needed. The fallthrough keyword, written as the last statement of a case, forces control into the next case's body.
Why does the Go compiler reject a file that imports a package it never uses?
basics
~20 sGo makes an unused import a hard compile error rather than a warning: dead imports slow builds, grow the dependency graph and mislead readers. Delete the line, or make it deliberate with a blank import, an underscore before the path.
What does a Go init() function do, and when does it run relative to main()?
basics
~10 sGo runs a package's init() functions automatically at startup: after that package's package-level variables are assigned and after every package it imports is fully initialized, but before main() begins. You cannot call init() yourself.
What does putting a Go package under a directory named internal/ do, and who can still import it?
basics
~20 sA package whose import path contains an internal element can be imported only by code inside the tree rooted at that internal/ directory's parent. Any other import fails at build time with 'use of internal package ... not allowed'.
In Go, what does `:=` inside an if block do when the enclosing function already declares that name?
basics
~20 sIt declares a new variable that lives only until that block's closing brace. The outer variable of the same name is hidden, not assigned, so whatever the inner block writes is lost when the block ends.
In Go, what makes an identifier visible to code in another package?
basics
~20 sThe case of its first letter. A name beginning with an upper-case letter is exported and can be used by importing packages; a name beginning with a lower-case letter is usable only inside the package that declares it.
Given `type UserID string`, why does `var id UserID = "u-1"` compile but `var s string = id` not?
basics
~20 sAn untyped string constant is assignable to any type whose underlying type is string, so the literal works. But UserID and string are two distinct named types, so moving a value between them needs an explicit conversion: string(id).
Which Go types can be compared with `==`, and which ones fail to compile?
basics
~20 sBooleans, numbers, strings, pointers, channels, interfaces, and structs or arrays built entirely from comparable parts support ==. Slices, maps and functions do not: the compiler rejects ==, and the only equality they allow is a comparison against nil.
In Go, which kinds of type can hold nil, and does nil mean the same thing for each?
basics
~20 sSix kinds of type can be nil: pointers, slices, maps, channels, functions and interfaces. nil is the zero value of each, not one shared value, so every kind has its own representation and its own rules about what you may safely do.
Why can a `chan int` be assigned to a `<-chan int` variable, but never the reverse?
basics
~20 sA bidirectional channel may be assigned to a receive-only or send-only variable, because that only removes capability. The reverse would invent capability the value never had, so it is neither assignable nor convertible. Direction is part of the static type.
What must be true for two Go interface values to be equal with `==`?
basics
~20 sTwo interface values are equal only when both hold nothing at all, or when their dynamic types are identical and their dynamic values are equal. An any holding int(1) never equals an any holding int64(1).