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 runes 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 thereflectpackage.)
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:











