Go structs are copied on assignment (and other things about Go I'd missed)

Go value semantics & common pitfalls

  • Many comments reiterate that in Go everything is passed by value (copied), including pointers, slices, maps, and channels; what’s copied is often a small descriptor that points to shared backing data.
  • A common gotcha: copying a struct, slice, or map variable copies the descriptor, so mutating through either copy can affect shared underlying data, but reassigning the local variable does not affect the original.
  • Range loops can copy elements; for _, v := range slice may repeatedly copy large structs, with both correctness and performance implications.
  • Named return values can be silently left at their zero value (e.g., err staying nil) if not explicitly assigned.

Pass-by-value vs pass-by-reference terminology

  • Long debate over whether modern languages meaningfully distinguish “pass-by-value” and “pass-by-reference.”
  • Several argue nearly all mainstream languages pass by value (often copying a pointer/reference), and that older “true pass-by-reference” semantics are largely historical.
  • Others insist the distinction still matters (e.g., C++/C# reference parameters) and should be taught, especially for performance and expressiveness.
  • Python’s model (variables as references to objects, arguments as copies of those references) is used extensively to illustrate confusion.

Slices, maps, and reference-like behavior

  • Slices and maps are described as small structs containing pointers; copying them copies the struct, not the underlying storage.
  • This leads to “reference-like” behavior that surprises newcomers, especially when appending to slices (which may reallocate and break sharing) versus mutating elements or map entries (which affects shared data).
  • Some see this as clear and consistent once understood; others find the hidden sharing and performance characteristics non-obvious and error-prone.

Language design, safety, and ergonomics

  • Some praise Go’s explicitness and C-like value semantics as easier to reason about than dynamic languages.
  • Others view many of these pitfalls as avoidable language design mistakes and argue alternative languages (e.g., Rust) avoid them.
  • There is recurring desire for better immutability and optional types in Go; attempts to retrofit immutability are said to be hard in an established language.

Learning, documentation, and expertise

  • Strong recommendations to read the official spec and certain Go books; the spec is praised as clear and accessible.
  • A Go “100 mistakes” collection is discussed: some find early items too basic, others defend starting simple and building up.
  • Several comments value public admission of knowledge gaps as a healthy senior-engineer trait; dissenting voices argue that senior developers, especially listing Go on a CV, should already know these memory details.