Go

What are zero-sized types' memory semantics? What do these print?

Question 350HardGo 1.22 to 1.25
type T struct {
    x int64
    z struct{}
}

type U struct {
    z struct{}
    x int64
}

func main() {
    fmt.Println(unsafe.Sizeof(T{}), unsafe.Sizeof(U{}), unsafe.Sizeof([100]struct{}{}))
    a, b := new(struct{}), new(struct{})
    fmt.Println(a == b) // ???
}

Output: 16 8 0, and then either true or false.

  • A zero-sized final field gets padding. Otherwise &t.z would point one past the end of the struct, possibly into the next object, and that pointer would keep the wrong object alive. So T is 16 bytes. Put zero-sized fields first.
  • Arrays of zero-sized types take no space: map[K]struct{} sets and chan struct{} signals cost nothing for the values.
  • The spec says "pointers to distinct zero-size variables may or may not be equal." Heap-allocated zero-size objects usually all point to runtime.zerobase. Whether these escape changes with how you print them, and the result can differ between compiler versions. Never rely on either answer.

What the interviewer is looking for: you know the tail-padding rule and the unspecified identity of zero-size values. A common bug is using &struct{}{} as a unique sentinel or context key. Use a named non-zero-size type, or an unexported type ctxKey int.

More on Memory, GC & Runtime Internals

All 38 Memory, GC & Runtime Internals questions