Join us
@kalpit-sharma-dev ă» Dec 18,2021 ă» 2 min read ă» 1293 views ă» Originally posted on faun.pub
Golang strings are immutable.
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:
rune
s may span multiple bytes.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 the reflect
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:
unsafe.Pointer
is an untyped pointer. It can point to any kind of value. Itâs a way to tell the compiler, âStep aside. I know what Iâm doing.â In this case, what weâre doing is converting a *string
into an unsafe.Pointer
into a *StringHeader
.
Now we have access to the underlying representation of the string
. Ever wondered how len("hello")
works? We can implement it ourselves:
Getting the length of a string is nice, but what about setting it? Hereâs what happens if we artificially extend the length of a string:
By changing the Len
field of the string header, we can expand the string to include other parts of memory. Itâs interesting to observe this behavior, but itâs not something youâd actually want to use.
Data: unsafe.Pointer
You may have noticed that StringHeader
has an unsafe.Pointer
field which points to the stringâs sequence of bytes. []byte
also has a sequence of bytes. In fact, we can build a []byte
from this pointer. Hereâs what a slice actually looks like:
Itâs a lot like StringHeader
, except it also has a Cap
(capacity) field. What happens if we build a SliceHeader
from the fields of a StringHeader
?
Weâve converted a string
into a []byte
. Itâs just as easy to go the other direction:
Both string
and []byte
headers are using the same Data
pointer, so they share memory. If you ever need to convert between string
and []byte
but there isnât enough memory to perform a copy, this might be useful.
A word of caution, however: string
is meant to be immutable, but []byte
is not. If you cast a string
to []byte
and try to modify the byte array, itâs a segmentation fault.
Casting in the other direction doesnât cause a segmentation fault, but then your supposedly immutable string
can change:
TRY IT âŠ. https://goplay.tools/snippet/PAjwbct_ohF
Join other developers and claim your FAUN account now!
Connectwise
@kalpit-sharma-devInfluence
Total Hits
Posts
Only registered users can post comments. Please, login or signup.