What are the runtime representations of Go's built-in types? What does this print on 64-bit?
Question 365HardGo 1.22 to 1.25
type Stringer interface{ String() string }
func main() {
var (
s string
sl []int
m map[string]int
ch chan int
e any
i Stringer
f func()
p *int
)
fmt.Println(unsafe.Sizeof(s), unsafe.Sizeof(sl), unsafe.Sizeof(m), unsafe.Sizeof(ch))
fmt.Println(unsafe.Sizeof(e), unsafe.Sizeof(i), unsafe.Sizeof(f), unsafe.Sizeof(p))
var ip *int
e = ip
fmt.Println(e == nil, ip == nil)
}
Output:
16 24 8 8
16 16 8 8
false true
- string: a data pointer and a length, 16 bytes. Assigning a string copies only this header.
- slice: pointer, len and cap, 24 bytes. That is why
appendresults must be reassigned: the callee's copy of the header changes, not yours. - map and chan: a single pointer to a runtime struct (the map header, or
hchan). That is why they behave like references when passed to functions, and why a nil map can be read but not written. - Empty interface (
eface): a type pointer plus a data pointer. Non-empty interface (iface): anitabpointer (the type plus its method table for this interface, cached globally) plus a data pointer. Both are 16 bytes. - func value: a pointer to a closure object whose first word is the code pointer, followed by the captured variables.
The last line is the classic nil interface trap: e holds type *int with a nil data pointer, so its type word is set and it is not equal to nil. Returning a typed nil pointer as an error produces the same bug.
What the interviewer is looking for: you can explain value semantics versus reference-like behaviour from the header layouts, and why storing a non-pointer value in an interface usually needs a heap allocation (the data word must be a pointer).
More on Memory, GC & Runtime Internals
- Q363How do you find a memory leak in production with pprof?
- Q364How does GOMAXPROCS interact with containers, and how does it affect GC?
- Q366What is bounds-check elimination and how do you help the compiler do it?
- Q367What is profile-guided optimisation (PGO) in Go and what does it actually change?
- Q368How does the runtime preempt goroutines, and what are GC safe points?