Well, yeah, I would expect that the language creators’ definition of the word “possible” excludes what you can do with unsafe due to the likely chance of nasal demon aviation.
You can even use assembly in Go, but it isn’t covered by backwards compatibility promise, similar as with unsafe. The strings.Builder OTOH is under promise to be kept working every time Go internals change in important ways.
I remember once someone said something similar about Python strings, and I thought, “this I have got to see,” and it turns out they were using ctypes to yank out the underlying C-string pointer and screw with it. I mean…yes? Play stupid games, win stupid prizes.
There are times it’s essential that some data is really and truly immutable. But you can do that even in C, just by making sure you allocate a string carefully and then mark the page it’s in as read-only. Saying Go (or Python, or Java, or…) strings are immutable is talking about what guarantees you can rely on within the language, not what you can accomplish by abusing the runtime.
This works because the Go spec is quite clear about the fact that strings are just slices of bytes. However, editing strings in this way is filled with footguns, particularly as all Go string literals in source are UTF-8, so there’s a very good chance that the string you are modifying is also UTF-8 (like in the example). Strings from other sources may come in other encodings.
When you operate on the slice via unsafe in this way, you are always operating on individual bytes rather than code points/runes, so you will need to be aware of the text encoding and the fact that you may only be editing part of a character. This is pretty much why Go tries to guide users away from mutating strings.
Well, yeah, I would expect that the language creators’ definition of the word “possible” excludes what you can do with
unsafe
due to the likely chance of nasal demon aviation.Indeed. It’s called unsafe for a reason.
To be even more pedantic, there aren’t any strings being modified - bytes are not strings.
But all strings are bytes.
[Comment removed by author]
But the assertion in the title was not that bytes are immutable.
It’s all about perspective.
strings.Builder
turns a byte slice into astring
. Read its source sometime – it’s pretty neat (and concise).You can even use assembly in Go, but it isn’t covered by backwards compatibility promise, similar as with unsafe. The strings.Builder OTOH is under promise to be kept working every time Go internals change in important ways.
I remember once someone said something similar about Python strings, and I thought, “this I have got to see,” and it turns out they were using
ctypes
to yank out the underlying C-string pointer and screw with it. I mean…yes? Play stupid games, win stupid prizes.There are times it’s essential that some data is really and truly immutable. But you can do that even in C, just by making sure you allocate a string carefully and then mark the page it’s in as read-only. Saying Go (or Python, or Java, or…) strings are immutable is talking about what guarantees you can rely on within the language, not what you can accomplish by abusing the runtime.
[Comment removed by author]
Well this made my day.
This works because the Go spec is quite clear about the fact that strings are just slices of bytes. However, editing strings in this way is filled with footguns, particularly as all Go string literals in source are UTF-8, so there’s a very good chance that the string you are modifying is also UTF-8 (like in the example). Strings from other sources may come in other encodings.
When you operate on the slice via
unsafe
in this way, you are always operating on individual bytes rather than code points/runes, so you will need to be aware of the text encoding and the fact that you may only be editing part of a character. This is pretty much why Go tries to guide users away from mutating strings.