Golang / Golang Internals and Memory Management Interview Questions
How are strings represented in Go and why are they immutable?
A Go string is a two-word struct similar to a slice header but without a capacity field: a ptr (unsafe.Pointer to the UTF-8 bytes) and a len (byte count). Strings are immutable — the bytes they point to cannot be modified through any string operation.
// String header: {ptr unsafe.Pointer, len int} s := "hello" fmt.Println(len(s)) // 5 (bytes, not runes) fmt.Println(s[0]) // 104 â byte value of 'h' // s[0] = 'H' // compile error: cannot assign to s[0] // UTF-8: len counts bytes, range counts runes emoji := "Go ð" fmt.Println(len(emoji)) // 7 (G=1, o=1, space=1, rocket=4 bytes) for i, r := range emoji { fmt.Printf("%d: %c\n", i, r) // i is byte offset, r is rune value } // String concatenation creates a NEW backing array each time // Avoid in loops â use strings.Builder instead var b strings.Builder for _, s := range words { b.WriteString(s) b.WriteByte(' ') } result := b.String() // single allocation // string <-> []byte conversion // Each conversion copies the bytes (different backing arrays) bytes := []byte(s) // copy into a new mutable byte slice s2 := string(bytes) // copy back â new immutable string // Zero-copy cast with unsafe (avoid unless in hot path + well-understood) // Not recommended for general use
Immutability allows strings to be safely shared without copying — multiple strings can point to the same backing byte array (e.g., a slice of a longer string). String constants are interned into read-only memory in the binary, so no heap allocation is needed for them. The strings.Builder type avoids repeated allocation by maintaining a []byte buffer and converting to string only at the end.
More Related questions...