Strings in Golang: Common Mistakes and Best Practices
In this story we want to discuss about strings in Golang and see some different scenarios to avoid common mistakes. Let’s dive in!
1. strings can be nil or not?
We already have a fundamental knowledge about strings in Golang but a good point to start is Golang strings cannot be nil, unless you use a pointer to strings.
When we creating a string variable as shown below the default value must be empty ""
. If we initialize it with nil
value, we will face with cannot use nil as string value in variable declaration
error. For example:
So, we can let the Golang initialize them for us or use ""
as default value:
If we insist to have a nil
value in a string
type variable, we should use pointers
as below:
However we have to be careful with this approach. Every time we want to assign a value to the name
variable we have to write more codes and also check for a nil
or previous value before assigning the new value. Take a look at this:
So, normal strings are easier and safer to use in Go.
2. strings are immutable
Strings in Golang are immutable and that means we can not change the value of each characters. For example:
The above code would result in compile-time error as cannot assign to temp[0]
.
A common mistake about changing an individual character of a string is as below:
Although the displayed result is what we expected, this is not the correct way to change a certain character.
This is because the single part we intend to modify could be stored in multiple bytes
and even if you are thinking about converting the variable to rune
type and mutate the part you want, I have to say, that it cannot be done, again because it could be placed in multiple runes and we need to move with caution!
3. strings are bytes
In Golang, strings are made up of bytes (slice of bytes) and some characters need to store in multiple bytes e.g: "♥"
So, when there is a need to determine length of a variable with the type of string, we must code carefully. For example:
The len
function returns the number of bytes in a string, not the number of characters and when we need to find out the number of runes of a string, we could use uft8.RuneCountIntString()
.
Another common misunderstand is to use uft8.RuneCountIntString()
to determine number of characters, but it’s not correct in every situation because a string variable might be spanned between multiple rune
. Look at this example:
4. strings index and range
In Golang, retrieving an individual part of a string by using its index will provide us with the uint
value of the character and will only retrieve the first byte
. However Inside a for
loop on a string
variable, we have access to the rune
value of each character:
Another quick note when iterating over a string is being aware of non-UTF8 characters which may exist in our variables and if Golang can’t understand it as UTF8, will use a unicode replacement not the actual value.
Because of that, it might be better to use a for
loop like below when we are dealing with strings in golang that have non-UTF8 characters:
This way, we will prevent any data change and always using actual value.
5. strings equality
We can always use a ==
to check for simple strings equality in Golang but if there is a hidden spot on our variables we should use unicode norm
package to normalize them before comparing two string variables:
6. efficient string building
Concatenating a large number of strings could be very inefficient. One of the best practices to compose strings efficiently is by using strings.Builder
:
This approach is way more faster and less memory consumption than the classic +
concatenating method and it will avoid the creation of unnecessary intermediate string. Also we can achieve this goal with bytes.Buffer
package.
That’s it. Here is the summary of what we have reviewed so far.
Summary
- Strings default value is
""
- The
len
andRuneCountIntString
functions have different behaviors - We should be careful about
for
loops and strings - Strings equality is where we need to be more accurate
If you like this article please Clap 👏 and follow me to get more of these Golang contents.
ALSO READ: