In general, immutable data is simpler to reason about, but it also means your program must allocate more memory to âchangeâ that data. Sometimes, your program canât afford that luxury. For example, there might not be any more memory to allocate. Another reason: you donât want to create more work for the garbage collector.
In C, a string is a null-terminated sequence of chars â char*
. Each char
is a single byte, and the string keeps going until thereâs a '\0'
character. If you pointed at an arbitrary memory location and called it a C string, youâd see every byte in order until you hit a zero.
In Go, string
is its own data type. At its core, itâs still a sequence of bytes, but:
- Itâs a fixed length. It doesnât just continue until a zero appears.
- It comes with extra information: its length.
- âCharactersâ or
rune
s may span multiple bytes. - Itâs immutable.
So string
in Go carries some additional structure compared to char*
in C. How does it do this? Itâs actually a struct:
Data
here is analogous to the C string, and Len
is the length. The Golang struct memory layout starts with the last field, so if you were to look at a string
under the microscope, youâd see Len
first and then a pointer to the string
's contents. (You can find documentation of these header structs in thereflect
package.)
Before we start inspecting strings by looking at their StringHeader
fields, how do we cast a string
to a StringHeader
in the first place? When you really need to convert from one Go type to another, use the unsafe
package: