A string is not a fundamental concept in hardware. It is an abstraction built on top of bytes. My version: String is just a high-level view of sequences of bytes or characters - Wikipedia

Let’s just try to learn how it is implemented in the real world

I will create a file and save the “hello world” ‘string” in it. Command:

 echo "hello world" > str

seems everything is good so far, it is just based command 😃

seems everything is good so far, it is just based command 😃

It is already saved. Let’s see how it is stored on disk:

image.png

The first command is showing as a 2-byte value, but the second one is showing each character of “hello world” with its hex value. The numbers (zeros) on the left are offsets added by the tool (not part of the data)

Better version:

Command:

Command: xxd -p str | fold -w2 | while read b; do printf "%s -> %b\n" "$b" "$(printf "\\x$b")"; done

If we look closely, the 20 and 0a are pointing to an empty but strange thing in the first image, where 0a is in yellow, but why? In the ASCII table 20 is equal to empty space, and it exists in our original text between two words, but the 0a is added by the echo command, and it means \n - a.k.a new line

So technically, that “hello world” is stored like this in memory (memory addresses are just examples in this case, it might vary):

                                                                 “hello world” in memory

                                                             “hello world” in memory 

In memory, strings are stored as contiguous bytes. Languages build abstractions on top of that.

Let’s see that connection in the Go programming language case, and other languages are similar to it

String in Go:

https://github.com/golang/go/blob/f5479628d36e6cdd63c39784b58fa7241abd3295/src/runtime/string.go#L291-L294

Note: in Python, it is a bit difficult to understand for non-C language users, so I thought it isn’t necessary, although it is almost identical to Go - https://github.com/python/cpython/blob/main/Include/cpython/unicodeobject.h

So, in go as you can see that stringStruct has only two values: one pointer to the first character of the string and the second is the length of that string - that’s it

Wait! Why is it not a slice of bytes []byte wouldn’t it make much more sense than just keeping a pointer? It is a language philosophy, because in Go, a string is immutable. If strings were slices, they would allow mutation through shared memory, which would break immutability guarantees, and also, there is no capacity value, because in the immutability case, always: cap=len