The Code Codex
Theme
← Notes / Fundamentals

note · text05 Oct 2024 · 1 min

Strings

A string is a sequence of characters, but in memory it is a sequence of bytes read through an encoding (UTF-8, UTF-16). That explains most surprises with text.

Immutable

In Go and in Java, strings are immutable: “changing” a string creates another one. That makes them safe to share between threads and to use as map keys.

The length depends on what you count
LanguageRepresentation"é""😀"
GoUTF-8 byteslen("é") = 2 byteslen("😀") = 4 bytes
JavaUTF-16 units"é".length() = 1"😀".length() = 2

To count characters the way a person would:

utf8.RuneCountInString("olá") // 3 (len("olá") is 4)
for i, r := range "olá" { // range walks runes, not bytes
fmt.Println(i, string(r))
}
"😀".codePointCount(0, "😀".length()); // 1
Concatenating in a loop

Since each concatenation creates a new string, joining thousands of pieces with + copies everything again on every iteration. Use a builder:

var b strings.Builder
for _, name := range names {
b.WriteString(name)
b.WriteString(", ")
}
result := b.String()
var sb = new StringBuilder();
for (String name : names) {
sb.append(name).append(", ");
}
String result = sb.toString();

To join with a separator, both have a shortcut: strings.Join(names, ", ") and String.join(", ", names).

Comparing in Java: equals, not ==

== checks whether they are the same object; equals compares the content. Sometimes == “works” because of the string pool, which makes the bug hard to find. In Go, == compares the content.

See also: strings, runes and bytes in Go and Data types.