UTF8
Go-Quelltexte sind per Definition in UTF-8, einer weit verbreiteten Kodierung des Unicode Zeichenvorrats. Damit sind auch String-Literale, wie sie in Quelltexten vorkommen, UTF-8.
text := "aö世界."
In diesem Beispiel ist der String text
10 Bytes lang: ein
ASCII-Zeichen (ein Byte), ein Umlaut (zwei Bytes), zwei Kanji (je drei Bytes)
und am Ende wieder ein ASCII-Zeichen.
fmt.Println(len(text)) // ergibt 10
Intern wird ein String als ein (unveränderlicher) Slice von Bytes
repräsentiert. Der Variablentyp string
wird jedoch, anders als
beispielsweise []byte
, als UTF-8 behandelt, was sich z.B. beim
range
Operator zeigt:
for i, c := range text {
fmt.Printf("%d -> %c\n", i, c)
}
ergibt:
0 -> a
1 -> ö
3 -> 世
6 -> 界
9 -> .
Der range
Operator iteriert also über die Unicode Codepunkte des UTF-8
Strings und gibt jeweils die Byte-Position des Zeichens (als Variable vom
Typ int
) und das Zeichen als Unicode (Typ rune
bzw. int32
) zurück.
Wenn man lieber direkt mit Unicode arbeiten möchte, bietet Go die Möglichkeit, einen String von UTF-8 nach Unicode zu konvertieren:
utext := []rune(text)
fmt.Println(len(utext))
for i, c := range utext {
fmt.Printf("%d -> %c\n", i, c)
}
ergibt die Ausgabe:
5
0 -> a
1 -> ö
2 -> 世
3 -> 界
4 -> .
In Unicode ist der Text also nur noch fünf Zeichen lang, und der range
Operator iteriert über die die fünf Elemente des []rune
Slice. Als
Unicode belegt der Text allerdings intern 20 Bytes (fünf Codepunkte zu je
vier Bytes), während der String in UTF-8 nur zehn Bytes lang ist.
Die Konvertierung von string
nach []rune
erfordert intern immer
ein Umkopieren der Daten.
Ebenso lässt sich ein String in seine Byte-Repräsentation umwandeln:
bytes := []byte(text)
fmt.Println(len(bytes))
for i, c := range bytes {
fmt.Printf("%d -> %d\n", i, c)
}
ergibt:
10
0 -> 97
1 -> 195
2 -> 182
3 -> 228
4 -> 184
5 -> 150
6 -> 231
7 -> 149
8 -> 140
9 -> 46
Der Slice ist also, wie der String, 10 Zeichen lang. Der range
Operator iteriert aber über jedes einzelne Zeichen; diese sind u.U.
nicht-druckbare Zeichen, daher werden sie in diesem Beispiel als
Dezimalzahl ausgegeben.